From 9f32ea202ae671225a3080d5aee1ce50ba7f8b5c Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 14 Mar 2022 20:24:37 -0500 Subject: [PATCH] SQLite compiling for dos! --- .gitignore | 1 + LICENSE | 5 + Makefile.djgpp | 7 +- buildPrerequisites.sh | 23 +- client/src/browser.c | 28 +- client/src/thirdparty/sqlite-3.4.2/Makefile | 629 + .../src/thirdparty/sqlite-3.4.2/Makefile.arm | 138 + .../src/thirdparty/sqlite-3.4.2/Makefile.in | 629 + .../sqlite-3.4.2/Makefile.linux-gcc | 128 + .../src/thirdparty/sqlite-3.4.2/Makefile.org | 622 + client/src/thirdparty/sqlite-3.4.2/README | 35 + client/src/thirdparty/sqlite-3.4.2/VERSION | 1 + client/src/thirdparty/sqlite-3.4.2/aclocal.m4 | 6470 +++++ .../thirdparty/sqlite-3.4.2/addopcodes.awk | 32 + .../sqlite-3.4.2/art/2005osaward.gif | 3 + .../thirdparty/sqlite-3.4.2/art/SQLite.eps | Bin 0 -> 24155 bytes .../thirdparty/sqlite-3.4.2/art/SQLite.gif | 3 + .../sqlite-3.4.2/art/SQLiteLogo3.tiff | Bin 0 -> 85156 bytes .../sqlite-3.4.2/art/SQLite_big.gif | 3 + .../thirdparty/sqlite-3.4.2/art/nocopy.gif | 3 + .../sqlite-3.4.2/art/powered_by_sqlite.gif | 3 + .../src/thirdparty/sqlite-3.4.2/config.guess | 1532 ++ client/src/thirdparty/sqlite-3.4.2/config.log | 1565 ++ .../src/thirdparty/sqlite-3.4.2/config.status | 774 + client/src/thirdparty/sqlite-3.4.2/config.sub | 1640 ++ client/src/thirdparty/sqlite-3.4.2/configure | 20477 ++++++++++++++++ .../src/thirdparty/sqlite-3.4.2/configure.ac | 582 + .../sqlite-3.4.2/contrib/sqlitecon.tcl | 679 + .../thirdparty/sqlite-3.4.2/doc/lemon.html | 892 + .../thirdparty/sqlite-3.4.2/doc/report1.txt | 121 + client/src/thirdparty/sqlite-3.4.2/ex1 | Bin 0 -> 2048 bytes .../thirdparty/sqlite-3.4.2/examples/c1.bat | 4 + .../thirdparty/sqlite-3.4.2/examples/c2.bat | 4 + .../thirdparty/sqlite-3.4.2/examples/c3.bat | 4 + .../sqlite-3.4.2/examples/example1.cpp | 36 + .../sqlite-3.4.2/examples/example2.cpp | 71 + .../sqlite-3.4.2/examples/example3.c | 64 + .../sqlite-3.4.2/examples/libsqlite3.a | Bin 0 -> 1839418 bytes .../sqlite-3.4.2/examples/notes.txt | 14 + .../sqlite-3.4.2/examples/sqlite3.h | 4804 ++++ .../thirdparty/sqlite-3.4.2/ext/README.txt | 2 + .../sqlite-3.4.2/ext/fts1/CVS/Entries | 15 + .../sqlite-3.4.2/ext/fts1/CVS/Repository | 1 + .../thirdparty/sqlite-3.4.2/ext/fts1/CVS/Root | 1 + .../sqlite-3.4.2/ext/fts1/README.txt | 2 + .../sqlite-3.4.2/ext/fts1/ft_hash.c | 404 + .../sqlite-3.4.2/ext/fts1/ft_hash.h | 111 + .../thirdparty/sqlite-3.4.2/ext/fts1/fts1.c | 3345 +++ .../thirdparty/sqlite-3.4.2/ext/fts1/fts1.h | 11 + .../sqlite-3.4.2/ext/fts1/fts1_hash.c | 369 + .../sqlite-3.4.2/ext/fts1/fts1_hash.h | 112 + .../sqlite-3.4.2/ext/fts1/fts1_porter.c | 643 + .../sqlite-3.4.2/ext/fts1/fts1_tokenizer.h | 90 + .../sqlite-3.4.2/ext/fts1/fts1_tokenizer1.c | 221 + .../sqlite-3.4.2/ext/fts1/fulltext.c | 1496 ++ .../sqlite-3.4.2/ext/fts1/fulltext.h | 11 + .../sqlite-3.4.2/ext/fts1/simple_tokenizer.c | 174 + .../sqlite-3.4.2/ext/fts1/tokenizer.h | 89 + .../sqlite-3.4.2/ext/fts2/CVS/Entries | 13 + .../sqlite-3.4.2/ext/fts2/CVS/Repository | 1 + .../thirdparty/sqlite-3.4.2/ext/fts2/CVS/Root | 1 + .../sqlite-3.4.2/ext/fts2/README.tokenizers | 133 + .../sqlite-3.4.2/ext/fts2/README.txt | 4 + .../thirdparty/sqlite-3.4.2/ext/fts2/fts2.c | 5937 +++++ .../thirdparty/sqlite-3.4.2/ext/fts2/fts2.h | 26 + .../sqlite-3.4.2/ext/fts2/fts2_hash.c | 369 + .../sqlite-3.4.2/ext/fts2/fts2_hash.h | 112 + .../sqlite-3.4.2/ext/fts2/fts2_icu.c | 257 + .../sqlite-3.4.2/ext/fts2/fts2_porter.c | 642 + .../sqlite-3.4.2/ext/fts2/fts2_tokenizer.c | 371 + .../sqlite-3.4.2/ext/fts2/fts2_tokenizer.h | 145 + .../sqlite-3.4.2/ext/fts2/fts2_tokenizer1.c | 229 + .../sqlite-3.4.2/ext/fts2/mkfts2amal.tcl | 116 + .../sqlite-3.4.2/ext/fts3/CVS/Entries | 13 + .../sqlite-3.4.2/ext/fts3/CVS/Repository | 1 + .../thirdparty/sqlite-3.4.2/ext/fts3/CVS/Root | 1 + .../sqlite-3.4.2/ext/fts3/README.tokenizers | 133 + .../sqlite-3.4.2/ext/fts3/README.txt | 4 + .../thirdparty/sqlite-3.4.2/ext/fts3/fts3.c | 6403 +++++ .../thirdparty/sqlite-3.4.2/ext/fts3/fts3.h | 26 + .../sqlite-3.4.2/ext/fts3/fts3_hash.c | 374 + .../sqlite-3.4.2/ext/fts3/fts3_hash.h | 110 + .../sqlite-3.4.2/ext/fts3/fts3_icu.c | 258 + .../sqlite-3.4.2/ext/fts3/fts3_porter.c | 642 + .../sqlite-3.4.2/ext/fts3/fts3_tokenizer.c | 371 + .../sqlite-3.4.2/ext/fts3/fts3_tokenizer.h | 145 + .../sqlite-3.4.2/ext/fts3/fts3_tokenizer1.c | 230 + .../sqlite-3.4.2/ext/fts3/mkfts3amal.tcl | 115 + .../sqlite-3.4.2/ext/icu/CVS/Entries | 3 + .../sqlite-3.4.2/ext/icu/CVS/Repository | 1 + .../thirdparty/sqlite-3.4.2/ext/icu/CVS/Root | 1 + .../sqlite-3.4.2/ext/icu/README.txt | 170 + .../src/thirdparty/sqlite-3.4.2/ext/icu/icu.c | 499 + client/src/thirdparty/sqlite-3.4.2/install.sh | 251 + client/src/thirdparty/sqlite-3.4.2/libtool | 7625 ++++++ client/src/thirdparty/sqlite-3.4.2/ltmain.sh | 6971 ++++++ client/src/thirdparty/sqlite-3.4.2/main.mk | 486 + client/src/thirdparty/sqlite-3.4.2/mkdll.sh | 46 + client/src/thirdparty/sqlite-3.4.2/mkextu.sh | 13 + client/src/thirdparty/sqlite-3.4.2/mkextw.sh | 22 + .../src/thirdparty/sqlite-3.4.2/mkopcodc.awk | 31 + .../src/thirdparty/sqlite-3.4.2/mkopcodec.awk | 31 + .../src/thirdparty/sqlite-3.4.2/mkopcodeh.awk | 157 + client/src/thirdparty/sqlite-3.4.2/mkso.sh | 29 + .../src/thirdparty/sqlite-3.4.2/notesDOS.txt | 18 + client/src/thirdparty/sqlite-3.4.2/publish.sh | 132 + .../thirdparty/sqlite-3.4.2/publish_osx.sh | 35 + .../src/thirdparty/sqlite-3.4.2/spec.template | 62 + .../src/thirdparty/sqlite-3.4.2/sqlite.pc.in | 12 + client/src/thirdparty/sqlite-3.4.2/sqlite3.1 | 229 + client/src/thirdparty/sqlite-3.4.2/sqlite3.pc | 13 + .../src/thirdparty/sqlite-3.4.2/sqlite3.pc.in | 13 + .../src/thirdparty/sqlite-3.4.2/src/alter.c | 630 + .../src/thirdparty/sqlite-3.4.2/src/analyze.c | 425 + .../src/thirdparty/sqlite-3.4.2/src/attach.c | 527 + client/src/thirdparty/sqlite-3.4.2/src/auth.c | 234 + .../src/thirdparty/sqlite-3.4.2/src/btmutex.c | 317 + .../src/thirdparty/sqlite-3.4.2/src/btree.c | 6943 ++++++ .../src/thirdparty/sqlite-3.4.2/src/btree.h | 203 + .../thirdparty/sqlite-3.4.2/src/btreeInt.h | 650 + .../src/thirdparty/sqlite-3.4.2/src/build.c | 3467 +++ .../thirdparty/sqlite-3.4.2/src/callback.c | 378 + .../thirdparty/sqlite-3.4.2/src/complete.c | 271 + client/src/thirdparty/sqlite-3.4.2/src/date.c | 1038 + .../src/thirdparty/sqlite-3.4.2/src/delete.c | 510 + .../sqlite-3.4.2/src/experimental.c | 37 + client/src/thirdparty/sqlite-3.4.2/src/expr.c | 2983 +++ .../src/thirdparty/sqlite-3.4.2/src/fault.c | 147 + client/src/thirdparty/sqlite-3.4.2/src/func.c | 1572 ++ client/src/thirdparty/sqlite-3.4.2/src/hash.c | 419 + client/src/thirdparty/sqlite-3.4.2/src/hash.h | 110 + .../src/thirdparty/sqlite-3.4.2/src/insert.c | 1663 ++ .../src/thirdparty/sqlite-3.4.2/src/journal.c | 238 + .../src/thirdparty/sqlite-3.4.2/src/legacy.c | 134 + .../src/thirdparty/sqlite-3.4.2/src/limits.h | 158 + .../src/thirdparty/sqlite-3.4.2/src/loadext.c | 518 + client/src/thirdparty/sqlite-3.4.2/src/main.c | 1509 ++ .../src/thirdparty/sqlite-3.4.2/src/malloc.c | 239 + client/src/thirdparty/sqlite-3.4.2/src/md5.c | 387 + client/src/thirdparty/sqlite-3.4.2/src/mem1.c | 232 + client/src/thirdparty/sqlite-3.4.2/src/mem2.c | 456 + client/src/thirdparty/sqlite-3.4.2/src/mem3.c | 653 + client/src/thirdparty/sqlite-3.4.2/src/mem4.c | 398 + .../src/thirdparty/sqlite-3.4.2/src/mutex.c | 126 + .../src/thirdparty/sqlite-3.4.2/src/mutex.h | 82 + .../thirdparty/sqlite-3.4.2/src/mutex_os2.c | 245 + .../thirdparty/sqlite-3.4.2/src/mutex_unix.c | 298 + .../thirdparty/sqlite-3.4.2/src/mutex_w32.c | 219 + client/src/thirdparty/sqlite-3.4.2/src/os.c | 267 + client/src/thirdparty/sqlite-3.4.2/src/os.h | 275 + .../thirdparty/sqlite-3.4.2/src/os_common.h | 127 + .../src/thirdparty/sqlite-3.4.2/src/os_os2.c | 989 + .../src/thirdparty/sqlite-3.4.2/src/os_os2.h | 73 + .../src/thirdparty/sqlite-3.4.2/src/os_test.c | 463 + .../src/thirdparty/sqlite-3.4.2/src/os_test.h | 40 + .../src/thirdparty/sqlite-3.4.2/src/os_unix.c | 2758 +++ .../src/thirdparty/sqlite-3.4.2/src/os_unix.h | 116 + .../src/thirdparty/sqlite-3.4.2/src/os_win.c | 1557 ++ .../src/thirdparty/sqlite-3.4.2/src/os_win.h | 40 + .../src/thirdparty/sqlite-3.4.2/src/pager.c | 5133 ++++ .../src/thirdparty/sqlite-3.4.2/src/pager.h | 125 + .../src/thirdparty/sqlite-3.4.2/src/parse.y | 1114 + .../src/thirdparty/sqlite-3.4.2/src/pragma.c | 1227 + .../src/thirdparty/sqlite-3.4.2/src/prepare.c | 768 + .../src/thirdparty/sqlite-3.4.2/src/printf.c | 904 + .../src/thirdparty/sqlite-3.4.2/src/random.c | 121 + .../src/thirdparty/sqlite-3.4.2/src/select.c | 3705 +++ .../src/thirdparty/sqlite-3.4.2/src/server.c | 485 + .../src/thirdparty/sqlite-3.4.2/src/shell.c | 2087 ++ .../thirdparty/sqlite-3.4.2/src/sqlite.h.in | 4804 ++++ .../thirdparty/sqlite-3.4.2/src/sqlite3ext.h | 350 + .../thirdparty/sqlite-3.4.2/src/sqliteInt.h | 2089 ++ .../thirdparty/sqlite-3.4.2/src/sqliteLimit.h | 179 + .../src/thirdparty/sqlite-3.4.2/src/table.c | 199 + .../thirdparty/sqlite-3.4.2/src/tclsqlite.c | 2591 ++ .../src/thirdparty/sqlite-3.4.2/src/test1.c | 4641 ++++ .../src/thirdparty/sqlite-3.4.2/src/test2.c | 619 + .../src/thirdparty/sqlite-3.4.2/src/test3.c | 1668 ++ .../src/thirdparty/sqlite-3.4.2/src/test4.c | 716 + .../src/thirdparty/sqlite-3.4.2/src/test5.c | 217 + .../src/thirdparty/sqlite-3.4.2/src/test6.c | 879 + .../src/thirdparty/sqlite-3.4.2/src/test7.c | 723 + .../src/thirdparty/sqlite-3.4.2/src/test8.c | 1218 + .../src/thirdparty/sqlite-3.4.2/src/test9.c | 193 + .../thirdparty/sqlite-3.4.2/src/test_async.c | 1708 ++ .../sqlite-3.4.2/src/test_autoext.c | 164 + .../thirdparty/sqlite-3.4.2/src/test_btree.c | 247 + .../thirdparty/sqlite-3.4.2/src/test_config.c | 477 + .../thirdparty/sqlite-3.4.2/src/test_devsym.c | 346 + .../thirdparty/sqlite-3.4.2/src/test_hexio.c | 336 + .../sqlite-3.4.2/src/test_loadext.c | 57 + .../thirdparty/sqlite-3.4.2/src/test_malloc.c | 513 + .../thirdparty/sqlite-3.4.2/src/test_md5.c | 388 + .../sqlite-3.4.2/src/test_onefile.c | 824 + .../thirdparty/sqlite-3.4.2/src/test_schema.c | 358 + .../thirdparty/sqlite-3.4.2/src/test_server.c | 491 + .../thirdparty/sqlite-3.4.2/src/test_tclvar.c | 327 + .../thirdparty/sqlite-3.4.2/src/test_thread.c | 332 + .../thirdparty/sqlite-3.4.2/src/tokenize.c | 503 + .../src/thirdparty/sqlite-3.4.2/src/trigger.c | 851 + .../src/thirdparty/sqlite-3.4.2/src/update.c | 669 + client/src/thirdparty/sqlite-3.4.2/src/utf.c | 545 + client/src/thirdparty/sqlite-3.4.2/src/util.c | 724 + .../src/thirdparty/sqlite-3.4.2/src/vacuum.c | 263 + client/src/thirdparty/sqlite-3.4.2/src/vdbe.c | 4816 ++++ client/src/thirdparty/sqlite-3.4.2/src/vdbe.h | 183 + .../src/thirdparty/sqlite-3.4.2/src/vdbeInt.h | 422 + .../src/thirdparty/sqlite-3.4.2/src/vdbeapi.c | 1066 + .../src/thirdparty/sqlite-3.4.2/src/vdbeaux.c | 2314 ++ .../thirdparty/sqlite-3.4.2/src/vdbeblob.c | 337 + .../thirdparty/sqlite-3.4.2/src/vdbefifo.c | 114 + .../src/thirdparty/sqlite-3.4.2/src/vdbemem.c | 1040 + client/src/thirdparty/sqlite-3.4.2/src/vtab.c | 798 + .../src/thirdparty/sqlite-3.4.2/src/where.c | 2843 +++ .../thirdparty/sqlite-3.4.2/tclinstaller.tcl | 32 + .../src/thirdparty/sqlite-3.4.2/tool/diffdb.c | 44 + .../thirdparty/sqlite-3.4.2/tool/fragck.tcl | 149 + .../src/thirdparty/sqlite-3.4.2/tool/lemon.c | 4822 ++++ .../src/thirdparty/sqlite-3.4.2/tool/lempar.c | 769 + .../thirdparty/sqlite-3.4.2/tool/memleak.awk | 29 + .../thirdparty/sqlite-3.4.2/tool/memleak2.awk | 29 + .../thirdparty/sqlite-3.4.2/tool/memleak3.tcl | 233 + .../sqlite-3.4.2/tool/mkkeywordhash.c | 559 + .../thirdparty/sqlite-3.4.2/tool/mkopts.tcl | 51 + .../sqlite-3.4.2/tool/mksqlite3c.tcl | 278 + .../sqlite-3.4.2/tool/mksqlite3internalh.tcl | 145 + .../thirdparty/sqlite-3.4.2/tool/omittest.tcl | 176 + .../sqlite-3.4.2/tool/opcodeDoc.awk | 23 + .../thirdparty/sqlite-3.4.2/tool/report1.txt | 66 + .../src/thirdparty/sqlite-3.4.2/tool/showdb.c | 86 + .../sqlite-3.4.2/tool/showjournal.c | 76 + .../thirdparty/sqlite-3.4.2/tool/soak1.tcl | 103 + .../sqlite-3.4.2/tool/space_used.tcl | 111 + .../sqlite-3.4.2/tool/spaceanal.tcl | 863 + .../sqlite-3.4.2/tool/speedtest.tcl | 275 + .../sqlite-3.4.2/tool/speedtest2.tcl | 207 + .../thirdparty/sqlite-3.4.2/www/34to35.tcl | 1006 + .../src/thirdparty/sqlite-3.4.2/www/arch.fig | 64 + .../src/thirdparty/sqlite-3.4.2/www/arch.gif | 3 + .../src/thirdparty/sqlite-3.4.2/www/arch.png | 3 + .../src/thirdparty/sqlite-3.4.2/www/arch.tcl | 221 + .../src/thirdparty/sqlite-3.4.2/www/arch2.fig | 123 + .../src/thirdparty/sqlite-3.4.2/www/arch2.gif | 3 + .../thirdparty/sqlite-3.4.2/www/arch2b.fig | 125 + .../src/thirdparty/sqlite-3.4.2/www/audit.tcl | 214 + .../thirdparty/sqlite-3.4.2/www/autoinc.tcl | 109 + .../sqlite-3.4.2/www/c_interface.tcl | 1116 + .../src/thirdparty/sqlite-3.4.2/www/capi3.tcl | 516 + .../thirdparty/sqlite-3.4.2/www/capi3ref.tcl | 1882 ++ .../thirdparty/sqlite-3.4.2/www/changes.tcl | 1880 ++ .../thirdparty/sqlite-3.4.2/www/common.tcl | 90 + .../thirdparty/sqlite-3.4.2/www/compile.tcl | 278 + .../thirdparty/sqlite-3.4.2/www/conflict.tcl | 91 + .../sqlite-3.4.2/www/copyright-release.html | 109 + .../sqlite-3.4.2/www/copyright-release.pdf | Bin 0 -> 2848 bytes .../thirdparty/sqlite-3.4.2/www/copyright.tcl | 126 + .../thirdparty/sqlite-3.4.2/www/datatype3.tcl | 440 + .../thirdparty/sqlite-3.4.2/www/datatypes.tcl | 243 + .../thirdparty/sqlite-3.4.2/www/different.tcl | 224 + .../thirdparty/sqlite-3.4.2/www/direct1b.gif | 3 + .../src/thirdparty/sqlite-3.4.2/www/docs.tcl | 159 + .../thirdparty/sqlite-3.4.2/www/download.tcl | 236 + .../thirdparty/sqlite-3.4.2/www/dynload.tcl | 70 + .../src/thirdparty/sqlite-3.4.2/www/faq.tcl | 463 + .../sqlite-3.4.2/www/fileformat.tcl | 785 + .../sqlite-3.4.2/www/formatchng.tcl | 285 + .../thirdparty/sqlite-3.4.2/www/fullscanb.gif | 3 + .../sqlite-3.4.2/www/index-ex1-x-b.gif | 3 + .../src/thirdparty/sqlite-3.4.2/www/index.tcl | 115 + .../sqlite-3.4.2/www/indirect1b1.gif | 3 + .../src/thirdparty/sqlite-3.4.2/www/lang.tcl | 2207 ++ .../thirdparty/sqlite-3.4.2/www/limits.tcl | 318 + .../thirdparty/sqlite-3.4.2/www/lockingv3.tcl | 570 + .../src/thirdparty/sqlite-3.4.2/www/mingw.tcl | 160 + .../thirdparty/sqlite-3.4.2/www/mkapidoc.tcl | 176 + .../src/thirdparty/sqlite-3.4.2/www/nulls.tcl | 329 + .../thirdparty/sqlite-3.4.2/www/oldnews.tcl | 509 + .../thirdparty/sqlite-3.4.2/www/omitted.tcl | 85 + .../thirdparty/sqlite-3.4.2/www/opcode.tcl | 243 + .../thirdparty/sqlite-3.4.2/www/optimizer.tcl | 265 + .../sqlite-3.4.2/www/optimizing.tcl | 15 + .../sqlite-3.4.2/www/optoverview.tcl | 516 + .../thirdparty/sqlite-3.4.2/www/pragma.tcl | 635 + .../sqlite-3.4.2/www/quickstart.tcl | 110 + .../thirdparty/sqlite-3.4.2/www/shared.gif | 3 + .../sqlite-3.4.2/www/sharedcache.tcl | 221 + .../src/thirdparty/sqlite-3.4.2/www/speed.tcl | 495 + .../thirdparty/sqlite-3.4.2/www/sqlite.tcl | 582 + .../thirdparty/sqlite-3.4.2/www/support.tcl | 79 + .../sqlite-3.4.2/www/table-ex1b2.gif | 3 + .../thirdparty/sqlite-3.4.2/www/tclsqlite.tcl | 666 + .../src/thirdparty/sqlite-3.4.2/www/vdbe.tcl | 1988 ++ .../thirdparty/sqlite-3.4.2/www/version3.tcl | 293 + .../thirdparty/sqlite-3.4.2/www/whentouse.tcl | 254 + shared/util.c | 39 + shared/util.h | 11 +- 296 files changed, 209948 insertions(+), 28 deletions(-) create mode 100644 client/src/thirdparty/sqlite-3.4.2/Makefile create mode 100644 client/src/thirdparty/sqlite-3.4.2/Makefile.arm create mode 100644 client/src/thirdparty/sqlite-3.4.2/Makefile.in create mode 100644 client/src/thirdparty/sqlite-3.4.2/Makefile.linux-gcc create mode 100644 client/src/thirdparty/sqlite-3.4.2/Makefile.org create mode 100644 client/src/thirdparty/sqlite-3.4.2/README create mode 100644 client/src/thirdparty/sqlite-3.4.2/VERSION create mode 100644 client/src/thirdparty/sqlite-3.4.2/aclocal.m4 create mode 100644 client/src/thirdparty/sqlite-3.4.2/addopcodes.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/2005osaward.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/SQLite.eps create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/SQLite.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/SQLiteLogo3.tiff create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/SQLite_big.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/nocopy.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/art/powered_by_sqlite.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/config.guess create mode 100644 client/src/thirdparty/sqlite-3.4.2/config.log create mode 100644 client/src/thirdparty/sqlite-3.4.2/config.status create mode 100644 client/src/thirdparty/sqlite-3.4.2/config.sub create mode 100644 client/src/thirdparty/sqlite-3.4.2/configure create mode 100644 client/src/thirdparty/sqlite-3.4.2/configure.ac create mode 100644 client/src/thirdparty/sqlite-3.4.2/contrib/sqlitecon.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/doc/lemon.html create mode 100644 client/src/thirdparty/sqlite-3.4.2/doc/report1.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/ex1 create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/c1.bat create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/c2.bat create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/c3.bat create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/example1.cpp create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/example2.cpp create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/example3.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/libsqlite3.a create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/notes.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/examples/sqlite3.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/README.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Entries create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Repository create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Root create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/README.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_porter.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer1.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/simple_tokenizer.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts1/tokenizer.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Entries create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Repository create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Root create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.tokenizers create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_icu.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_porter.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer1.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts2/mkfts2amal.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Entries create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Repository create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Root create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.tokenizers create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_icu.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_porter.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer1.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/fts3/mkfts3amal.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Entries create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Repository create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Root create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/icu/README.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/ext/icu/icu.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/install.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/libtool create mode 100644 client/src/thirdparty/sqlite-3.4.2/ltmain.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/main.mk create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkdll.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkextu.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkextw.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkopcodc.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkopcodec.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkopcodeh.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/mkso.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/notesDOS.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/publish.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/publish_osx.sh create mode 100644 client/src/thirdparty/sqlite-3.4.2/spec.template create mode 100644 client/src/thirdparty/sqlite-3.4.2/sqlite.pc.in create mode 100644 client/src/thirdparty/sqlite-3.4.2/sqlite3.1 create mode 100644 client/src/thirdparty/sqlite-3.4.2/sqlite3.pc create mode 100644 client/src/thirdparty/sqlite-3.4.2/sqlite3.pc.in create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/alter.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/analyze.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/attach.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/auth.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/btmutex.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/btree.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/btree.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/btreeInt.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/build.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/callback.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/complete.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/date.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/delete.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/experimental.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/expr.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/fault.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/func.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/hash.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/hash.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/insert.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/journal.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/legacy.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/limits.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/loadext.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/main.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/malloc.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/md5.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mem1.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mem2.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mem3.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mem4.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mutex.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mutex.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mutex_os2.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mutex_unix.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/mutex_w32.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_common.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_os2.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_os2.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_test.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_test.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_unix.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_unix.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_win.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/os_win.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/pager.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/pager.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/parse.y create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/pragma.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/prepare.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/printf.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/random.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/select.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/server.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/shell.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/sqlite.h.in create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/sqlite3ext.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/sqliteInt.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/sqliteLimit.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/table.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/tclsqlite.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test1.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test2.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test3.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test4.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test5.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test6.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test7.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test8.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test9.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_async.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_autoext.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_btree.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_config.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_devsym.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_hexio.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_loadext.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_malloc.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_md5.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_onefile.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_schema.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_server.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_tclvar.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/test_thread.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/tokenize.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/trigger.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/update.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/utf.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/util.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vacuum.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbe.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbe.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbeInt.h create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbeapi.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbeaux.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbeblob.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbefifo.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vdbemem.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/vtab.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/src/where.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tclinstaller.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/diffdb.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/fragck.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/lemon.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/lempar.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/memleak.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/memleak2.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/memleak3.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/mkkeywordhash.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/mkopts.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/mksqlite3c.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/mksqlite3internalh.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/omittest.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/opcodeDoc.awk create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/report1.txt create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/showdb.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/showjournal.c create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/soak1.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/space_used.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/spaceanal.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/speedtest.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/tool/speedtest2.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/34to35.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch.fig create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch.png create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch2.fig create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch2.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/arch2b.fig create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/audit.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/autoinc.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/c_interface.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/capi3.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/capi3ref.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/changes.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/common.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/compile.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/conflict.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/copyright-release.html create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/copyright-release.pdf create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/copyright.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/datatype3.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/datatypes.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/different.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/direct1b.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/docs.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/download.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/dynload.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/faq.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/fileformat.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/formatchng.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/fullscanb.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/index-ex1-x-b.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/index.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/indirect1b1.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/lang.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/limits.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/lockingv3.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/mingw.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/mkapidoc.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/nulls.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/oldnews.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/omitted.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/opcode.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/optimizer.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/optimizing.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/optoverview.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/pragma.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/quickstart.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/shared.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/sharedcache.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/speed.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/sqlite.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/support.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/table-ex1b2.gif create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/tclsqlite.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/vdbe.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/version3.tcl create mode 100644 client/src/thirdparty/sqlite-3.4.2/www/whentouse.tcl diff --git a/.gitignore b/.gitignore index d93ba10..8a94e30 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ obj/ retired/ test/ doors/ +client/src/thirdparty/sqlite-3.4.2/build */out/ diff --git a/LICENSE b/LICENSE index 284f6bb..e796eed 100644 --- a/LICENSE +++ b/LICENSE @@ -58,6 +58,11 @@ SHA256 https://github.com/ilvn/SHA256 MIT +SQLite 3.4.2 +------------ +https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/1.2/repos/pkg-html/sqlite.html +Public Domain + stb_ds.h -------- https://github.com/nothings/stb diff --git a/Makefile.djgpp b/Makefile.djgpp index de02ed2..11b0d21 100644 --- a/Makefile.djgpp +++ b/Makefile.djgpp @@ -35,10 +35,10 @@ BINDIR = bin CFLAGS := $(DEBUG) #CFLAGS += -DALLEGRONOTAVAIL -DALLEGRONOTPROGS -DDZCOMM_SRC CFLAGS += -I$(SRCDIR)/client/src -I$(SRCDIR)/client/src/system -I$(SRCDIR)/client/src/dos -I$(SRCDIR)/client/src/gui -I$(SRCDIR)/client/src/thirdparty -CFLAGS += -I$(SRCDIR)/shared -I$(SRCDIR)/shared/thirdparty +CFLAGS += -I$(SRCDIR)/client/src/thirdparty/sqlite-3.4.2/build -I$(SRCDIR)/shared -I$(SRCDIR)/shared/thirdparty #CFLAGS += -I$(SRCDIR)/client/src/thirdparty/dzcomm -I$(SRCDIR)/client/src/thirdparty/dzcomm/include CPPFLAGS := -LDFLAGS := +LDFLAGS := -L$(SRCDIR)/client/src/thirdparty/sqlite-3.4.2/build/.libs -lsqlite3 #LDFLAGS += -L$(SRCDIR)/client/src/thirdparty/dzcomm -ldzcom PREFIX := /usr/local TARGET_ARCH := @@ -58,7 +58,7 @@ ALL_LDLIBS := -lc # Source, Binaries, Dependencies -SRC := $(shell find $(SRCDIR) -type f -name '*.c' | grep -v '/linux/' | grep -v '/server/' | grep -v '/primes/' | grep -v '/font/' | grep -v '/precache/' | grep -v '/retired/' | grep -v '/test/') +SRC := $(shell find $(SRCDIR) -type f -name '*.c' | grep -v '/linux/' | grep -v '/server/' | grep -v '/primes/' | grep -v '/font/' | grep -v '/precache/' | grep -v '/retired/' | grep -v '/test/' | grep -v '/sqlite-3.4.2/') OBJ := $(patsubst $(SRCDIR)/%,$(OBJDIR)/%,$(SRC:.c=.o)) DEP := $(OBJ:.o=.d) BIN := $(BINDIR)/$(TARGET) @@ -126,4 +126,3 @@ install: $(BIN) clean: $(RM) $(OBJ) $(DEP) $(BIN) $(RMDIR) $(OBJDIR) $(BINDIR) 2> /dev/null; true - diff --git a/buildPrerequisites.sh b/buildPrerequisites.sh index 894d595..65f6208 100755 --- a/buildPrerequisites.sh +++ b/buildPrerequisites.sh @@ -78,11 +78,22 @@ function outputLicense() { } -pushd font/data -createEmbeddedBinary vga8x14 dat ../../client/src/embedded -popd +# Include DJGPP into the path for this script +PATH=/opt/cross/djgpp/bin:$PATH -pushd client/data -createEmbeddedBinary mouse png ../../client/src/embedded -popd +#pushd font/data +#createEmbeddedBinary vga8x14 dat ../../client/src/embedded +#popd +# Build SQLite +pushd client/src/thirdparty/sqlite-3.4.2 +[[ -d build ]] && rm -rf build +mkdir -p build +cd build +sh ../configure \ + --disable-tcl \ + --disable-threadsafe\ + --build=x86_64-linux-gnu \ + --host=i586-pc-msdosdjgpp +make +popd diff --git a/client/src/browser.c b/client/src/browser.c index d89a488..aebae23 100644 --- a/client/src/browser.c +++ b/client/src/browser.c @@ -29,6 +29,7 @@ #include "listbox.h" #include "network.h" +#include "util.h" static WindowT *_winBrowser = NULL; @@ -62,6 +63,8 @@ static void packetHandler(PacketDecodeDataT *packet); void browserShow(void) { + char **lines = NULL; + TagItemT uiBrowser[] = { T_START, T_WINDOW, O(_winBrowser), @@ -200,19 +203,18 @@ void browserShow(void) { guiDebugAreaShow(W(_btnBoxTab)); guiDebugAreaShow(W(_btnInfoTab)); - // 123456789012345678901234567890123456789012345678901234567 - listboxItemAdd(_lstDescription, "The Post-Terran Minerals Corporation (PTMC) digs up"); - listboxItemAdd(_lstDescription, "minerals on all nine planets of the solar system,"); - listboxItemAdd(_lstDescription, "employing humans and robots to do its job. Unfortunately,"); - listboxItemAdd(_lstDescription, "the mining robots are now being controlled by a hacker,"); - listboxItemAdd(_lstDescription, "and have taken the human workers hostage. The PTMC has"); - listboxItemAdd(_lstDescription, "tried to get the robots back under their control, but"); - listboxItemAdd(_lstDescription, "communication with the mining stations has been lost. In"); - listboxItemAdd(_lstDescription, "desperation, the PTMC modifies a Pyro-GX ship for combat"); - listboxItemAdd(_lstDescription, "and hires a mercenary, codenamed 'Material Defender', to"); - listboxItemAdd(_lstDescription, "fly it. The mission is to destroy the infected mines and"); - listboxItemAdd(_lstDescription, "rescue human hostages, destroying any hostile robot that"); - listboxItemAdd(_lstDescription, "gets in the way."); + lines = utilWrapText( + "The Post-Terran Minerals Corporation (PTMC) digs up minerals on all nine planets of the solar system, " + "employing humans and robots to do its job. Unfortunately, the mining robots are now being controlled by a hacker, " + "and have taken the human workers hostage. The PTMC has tried to get the robots back under their control, but " + "communication with the mining stations has been lost. In desperation, the PTMC modifies a Pyro-GX ship for combat " + "and hires a mercenary, codenamed 'Material Defender', to fly it. The mission is to destroy the infected mines and " + "rescue human hostages, destroying any hostile robot that gets in the way.", 57); + while (arrlen(lines) > 0) { + listboxItemAdd(_lstDescription, lines[0]); + DEL(lines[0]); + arrdel(lines, 0); + } listboxItemAdd(_lstInfo, "123456789012345678901234567890123456789012345678901234567"); listboxItemAdd(_lstInfo, "2"); diff --git a/client/src/thirdparty/sqlite-3.4.2/Makefile b/client/src/thirdparty/sqlite-3.4.2/Makefile new file mode 100644 index 0000000..f56a0c4 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/Makefile @@ -0,0 +1,629 @@ +#!/usr/make +# +# Makefile for SQLITE +# +# This makefile is suppose to be configured automatically using the +# autoconf. But if that does not work for you, you can configure +# the makefile manually. Just set the parameters below to values that +# work well for your system. +# +# If the configure script does not work out-of-the-box, you might +# be able to get it to work by giving it some hints. See the comment +# at the beginning of configure.in for additional information. +# + +# 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 + +# C Compile 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.) +# +TCC = gcc -g -O2 -I. -I${TOP}/src + +# 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. +# +TCC += -DNDEBUG + +# Compiler options needed for programs that use the TCL library. +# +TCC += + +# The library that programs using TCL must link against. +# +LIBTCL = + +# Compiler options needed for programs that use the readline() library. +# +READLINE_FLAGS = -DHAVE_READLINE=0 + +# The library that programs using readline() must link against. +# +LIBREADLINE = + +# Should the database engine be compiled threadsafe +# +TCC += -DSQLITE_THREADSAFE=0 + +# The pthreads library if needed +# +LIBPTHREAD= + +# Do threads override each others locks by default (1), or do we test (-1) +# +TCC += -DSQLITE_THREAD_OVERRIDE_LOCK=-1 + +# The fdatasync library +TLIBS = + +# Flags controlling use of the in memory btree implementation +# +# 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. +# +TEMP_STORE = -DTEMP_STORE=1 + +# Version numbers and release number for the SQLite being compiled. +# +VERSION = 3.5 +VERSION_NUMBER = 3005006 +RELEASE = 3.5.6 + +# Filename extensions +# +BEXE = .exe +TEXE = .exe + +# The following variable is "1" if the configure script was able to locate +# the tclConfig.sh file. It is an empty string otherwise. When this +# variable is "1", the TCL extension library (libtclsqlite3.so) is built +# and installed. +# +HAVE_TCL = + +# The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib" +# +SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@ + +# The directory into which to store package information for + +# Some standard variables and programs +# +prefix = /dev/env/DJDIR +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +INSTALL = /dev/env/DJDIR/bin/ginstall -c +LIBTOOL = ./libtool +ALLOWRELEASE = + +# libtool compile/link/install +LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) +LTLINK = $(LIBTOOL) --mode=link $(TCC) +LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) + +# nawk compatible awk. +NAWK = gawk + +# You should not have to change anything below this line +############################################################################### +TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1 + +# Object files for the SQLite library. +# +LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btmutex.lo btree.lo build.lo \ + callback.lo complete.lo date.lo \ + delete.lo expr.lo fault.lo func.lo \ + hash.lo journal.lo insert.lo loadext.lo \ + main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mutex.lo \ + mutex_os2.lo mutex_unix.lo mutex_w32.lo \ + opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ + pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ + select.lo table.lo tokenize.lo trigger.lo update.lo \ + util.lo vacuum.lo \ + vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \ + where.lo utf.lo legacy.lo vtab.lo + +# 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/btmutex.c \ + $(TOP)/src/btree.c \ + $(TOP)/src/btree.h \ + $(TOP)/src/build.c \ + $(TOP)/src/callback.c \ + $(TOP)/src/complete.c \ + $(TOP)/src/date.c \ + $(TOP)/src/delete.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/fault.c \ + $(TOP)/src/func.c \ + $(TOP)/src/hash.c \ + $(TOP)/src/hash.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/mem1.c \ + $(TOP)/src/mem2.c \ + $(TOP)/src/mem3.c \ + $(TOP)/src/mem4.c \ + $(TOP)/src/mutex.c \ + $(TOP)/src/mutex_os2.c \ + $(TOP)/src/mutex_unix.c \ + $(TOP)/src/mutex_w32.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_unix.c \ + $(TOP)/src/os_win.c \ + $(TOP)/src/os_os2.c \ + $(TOP)/src/pager.c \ + $(TOP)/src/pager.h \ + $(TOP)/src/parse.y \ + $(TOP)/src/pragma.c \ + $(TOP)/src/prepare.c \ + $(TOP)/src/printf.c \ + $(TOP)/src/random.c \ + $(TOP)/src/select.c \ + $(TOP)/src/shell.c \ + $(TOP)/src/sqlite.h.in \ + $(TOP)/src/sqliteInt.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/vdbefifo.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vtab.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 + + +# Source code to the test files. +# +TESTSRC = \ + $(TOP)/src/attach.c \ + $(TOP)/src/btree.c \ + $(TOP)/src/build.c \ + $(TOP)/src/date.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/func.c \ + $(TOP)/src/insert.c \ + $(TOP)/src/malloc.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_os2.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/select.c \ + $(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_btree.c \ + $(TOP)/src/test_config.c \ + $(TOP)/src/test_devsym.c \ + $(TOP)/src/test_hexio.c \ + $(TOP)/src/test_malloc.c \ + $(TOP)/src/test_md5.c \ + $(TOP)/src/test_onefile.c \ + $(TOP)/src/test_schema.c \ + $(TOP)/src/test_server.c \ + $(TOP)/src/test_tclvar.c \ + $(TOP)/src/test_thread.c \ + $(TOP)/src/tokenize.c \ + $(TOP)/src/utf.c \ + $(TOP)/src/util.c \ + $(TOP)/src/vdbe.c \ + $(TOP)/src/vdbeapi.c \ + $(TOP)/src/vdbeaux.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/where.c \ + parse.c + +# Header files used by all library source files. +# +HDR = \ + sqlite3.h \ + $(TOP)/src/btree.h \ + $(TOP)/src/btreeInt.h \ + $(TOP)/src/hash.h \ + $(TOP)/src/sqliteLimit.h \ + $(TOP)/src/mutex.h \ + opcodes.h \ + $(TOP)/src/os.h \ + $(TOP)/src/os_common.h \ + $(TOP)/src/sqlite3ext.h \ + $(TOP)/src/sqliteInt.h \ + $(TOP)/src/vdbe.h \ + parse.h + +# Header files used by extensions +# +HDR += \ + $(TOP)/ext/fts1/fts1.h \ + $(TOP)/ext/fts1/fts1_hash.h \ + $(TOP)/ext/fts1/fts1_tokenizer.h + +# Header files used by the VDBE submodule +# +VDBEHDR = \ + $(HDR) \ + $(TOP)/src/vdbeInt.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.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la) + +Makefile: $(TOP)/Makefile.in + ./config.status + +# Generate the file "last_change" which contains the date of change +# of the most recently modified source code file +# +last_change: $(SRC) + cat $(SRC) | grep '$$Id: ' | sort -k 5 | tail -1 \ + | $(NAWK) '{print $$5,$$6}' >last_change + +libsqlite3.la: $(LIBOBJ) + $(LTLINK) -o libsqlite3.la $(LIBOBJ) $(LIBPTHREAD) \ + ${ALLOWRELEASE} -rpath $(libdir) -version-info "8:6:8" + +libtclsqlite3.la: tclsqlite.lo libsqlite3.la + $(LTLINK) -o libtclsqlite3.la tclsqlite.lo \ + $(LIBOBJ) $(LIBPTHREAD) \ + -rpath $(libdir)/sqlite \ + -version-info "8:6:8" + +sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h + $(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \ + -o $@ $(TOP)/src/shell.c libsqlite3.la \ + $(LIBREADLINE) $(TLIBS) + +# 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) parse.c opcodes.c keywordhash.h $(VDBEHDR) + rm -rf tsrc + mkdir -p tsrc + cp $(SRC) $(VDBEHDR) tsrc + rm tsrc/sqlite.h.in tsrc/parse.y + cp parse.c opcodes.c keywordhash.h tsrc + +sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl + tclsh $(TOP)/tool/mksqlite3c.tcl + +# Rules to build the LEMON compiler generator +# +lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c + $(BCC) -o lemon$(BEXE) $(TOP)/tool/lemon.c + cp $(TOP)/tool/lempar.c . + + +# Rules to build individual files +# +alter.lo: $(TOP)/src/alter.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/alter.c + +analyze.lo: $(TOP)/src/analyze.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/analyze.c + +attach.lo: $(TOP)/src/attach.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/attach.c + +auth.lo: $(TOP)/src/auth.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/auth.c + +btmutex.lo: $(TOP)/src/btmutex.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/btmutex.c + +btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h + $(LTCOMPILE) -c $(TOP)/src/btree.c + +build.lo: $(TOP)/src/build.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/build.c + +callback.lo: $(TOP)/src/callback.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/callback.c + +complete.lo: $(TOP)/src/complete.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/complete.c + +date.lo: $(TOP)/src/date.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/date.c + +delete.lo: $(TOP)/src/delete.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/delete.c + +expr.lo: $(TOP)/src/expr.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/expr.c + +fault.lo: $(TOP)/src/fault.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/fault.c + +func.lo: $(TOP)/src/func.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/func.c + +hash.lo: $(TOP)/src/hash.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/hash.c + +insert.lo: $(TOP)/src/insert.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/insert.c + +journal.lo: $(TOP)/src/journal.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/journal.c + +legacy.lo: $(TOP)/src/legacy.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/legacy.c + +loadext.lo: $(TOP)/src/loadext.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/loadext.c + +main.lo: $(TOP)/src/main.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c + +malloc.lo: $(TOP)/src/malloc.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c + +mem1.lo: $(TOP)/src/mem1.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c + +mem2.lo: $(TOP)/src/mem2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem2.c + +mem3.lo: $(TOP)/src/mem3.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c + +mem4.lo: $(TOP)/src/mem4.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem4.c + +mutex.lo: $(TOP)/src/mutex.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c + +mutex_os2.lo: $(TOP)/src/mutex_os2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_os2.c + +mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c + +mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c + +pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h + $(LTCOMPILE) -c $(TOP)/src/pager.c + +opcodes.lo: opcodes.c + $(LTCOMPILE) -c opcodes.c + +opcodes.c: opcodes.h $(TOP)/mkopcodec.awk + sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >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 + +os.lo: $(TOP)/src/os.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os.c + +os_unix.lo: $(TOP)/src/os_unix.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_unix.c + +os_win.lo: $(TOP)/src/os_win.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_win.c + +os_os2.lo: $(TOP)/src/os_os2.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_os2.c + +parse.lo: parse.c $(HDR) + $(LTCOMPILE) -c parse.c + +parse.h: parse.c + +parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk + cp $(TOP)/src/parse.y . + ./lemon$(BEXE) $(OPTS) parse.y + mv parse.h parse.h.temp + $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h + +pragma.lo: $(TOP)/src/pragma.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/pragma.c + +prepare.lo: $(TOP)/src/prepare.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/prepare.c + +printf.lo: $(TOP)/src/printf.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/printf.c + +random.lo: $(TOP)/src/random.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/random.c + +select.lo: $(TOP)/src/select.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/select.c + +sqlite3.h: $(TOP)/src/sqlite.h.in + sed -e s/--VERS--/$(RELEASE)/ $(TOP)/src/sqlite.h.in | \ + sed -e s/--VERSION-NUMBER--/$(VERSION_NUMBER)/ >sqlite3.h + +table.lo: $(TOP)/src/table.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/table.c + +tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/tclsqlite.c + +tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR) + $(LTCOMPILE) -c $(TOP)/src/tokenize.c + +keywordhash.h: $(TOP)/tool/mkkeywordhash.c + $(BCC) -o mkkeywordhash$(BEXE) $(OPTS) $(TOP)/tool/mkkeywordhash.c + ./mkkeywordhash$(BEXE) >keywordhash.h + +trigger.lo: $(TOP)/src/trigger.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/trigger.c + +update.lo: $(TOP)/src/update.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/update.c + +utf.lo: $(TOP)/src/utf.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/utf.c + +util.lo: $(TOP)/src/util.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/util.c + +vacuum.lo: $(TOP)/src/vacuum.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/vacuum.c + +vdbe.lo: $(TOP)/src/vdbe.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbe.c + +vdbeapi.lo: $(TOP)/src/vdbeapi.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeapi.c + +vdbeaux.lo: $(TOP)/src/vdbeaux.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeaux.c + +vdbeblob.lo: $(TOP)/src/vdbeblob.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeblob.c + +vdbefifo.lo: $(TOP)/src/vdbefifo.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbefifo.c + +vdbemem.lo: $(TOP)/src/vdbemem.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbemem.c + +vtab.lo: $(TOP)/src/vtab.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vtab.c + +where.lo: $(TOP)/src/where.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/where.c + +tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -DTCL_USE_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite3: tclsqlite-shell.lo libsqlite3.la + $(LTLINK) -o tclsqlite3 tclsqlite-shell.lo \ + libsqlite3.la $(LIBTCL) + +testfixture$(TEXE): $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) + $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \ + -DSQLITE_NO_SYNC=1 $(TEMP_STORE) \ + -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libsqlite3.la $(LIBTCL) + + +fulltest: testfixture$(TEXE) sqlite3$(TEXE) + ./testfixture $(TOP)/test/all.test + +test: testfixture$(TEXE) sqlite3$(TEXE) + ./testfixture $(TOP)/test/quick.test + +sqlite3_analyzer$(TEXE): $(TOP)/src/tclsqlite.c libtclsqlite3.la \ + $(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 + $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 $(TEMP_STORE)\ + -o sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libtclsqlite3.la $(LIBTCL) + + +install: sqlite3$(BEXE) libsqlite3.la sqlite3.h ${HAVE_TCL:1=tcl_install} + $(INSTALL) -d $(DESTDIR)$(libdir) + $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) + $(INSTALL) -d $(DESTDIR)$(exec_prefix)/bin + $(LTINSTALL) sqlite3$(BEXE) $(DESTDIR)$(exec_prefix)/bin + $(INSTALL) -d $(DESTDIR)$(prefix)/include + $(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(prefix)/include + $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(prefix)/include + $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig; + $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(libdir)/pkgconfig; + +tcl_install: libtclsqlite3.la + tclsh $(TOP)/tclinstaller.tcl $(VERSION) + +clean: + rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la + rm -f sqlite3.h opcodes.* + rm -rf .libs .deps + rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz + rm -f mkkeywordhash$(BEXE) keywordhash.h + rm -f $(PUBLISH) + rm -f *.da *.bb *.bbg gmon.out + rm -f testfixture$(TEXE) test.db + rm -f common.tcl + rm -f sqlite3.dll sqlite3.lib sqlite3.def + +distclean: clean + rm -f config.log config.status libtool Makefile config.h sqlite3.pc + +# +# Windows section +# +dll: sqlite3.dll + +REAL_LIBOBJ = $(LIBOBJ:%.lo=.libs/%.o) + +$(REAL_LIBOBJ): $(LIBOBJ) + +sqlite3.def: $(REAL_LIBOBJ) + echo 'EXPORTS' >sqlite3.def + nm $(REAL_LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \ + | sed 's/^.* _//' >>sqlite3.def + +sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def + $(TCC) -shared -o sqlite3.dll sqlite3.def \ + -Wl,"--strip-all" $(REAL_LIBOBJ) diff --git a/client/src/thirdparty/sqlite-3.4.2/Makefile.arm b/client/src/thirdparty/sqlite-3.4.2/Makefile.arm new file mode 100644 index 0000000..921826b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/Makefile.arm @@ -0,0 +1,138 @@ +#!/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 -DOS_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.4linux +#TCL_FLAGS = -I/home/drh/tcltk/8.4win -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.4linux/libtcl8.4g.a -lm -ldl +#LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.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/client/src/thirdparty/sqlite-3.4.2/Makefile.in b/client/src/thirdparty/sqlite-3.4.2/Makefile.in new file mode 100644 index 0000000..6e01c4c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/Makefile.in @@ -0,0 +1,629 @@ +#!/usr/make +# +# Makefile for SQLITE +# +# This makefile is suppose to be configured automatically using the +# autoconf. But if that does not work for you, you can configure +# the makefile manually. Just set the parameters below to values that +# work well for your system. +# +# If the configure script does not work out-of-the-box, you might +# be able to get it to work by giving it some hints. See the comment +# at the beginning of configure.in for additional information. +# + +# The toplevel directory of the source tree. This is the directory +# that contains this "Makefile.in" and the "configure.in" script. +# +TOP = @srcdir@ + +# C Compiler and options for use in building executables that +# will run on the platform that is doing the build. +# +BCC = @BUILD_CC@ @BUILD_CFLAGS@ + +# C Compile 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.) +# +TCC = @CC@ @CFLAGS@ -I. -I${TOP}/src + +# 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. +# +TCC += @TARGET_DEBUG@ @XTHREADCONNECT@ + +# Compiler options needed for programs that use the TCL library. +# +TCC += @TCL_INCLUDE_SPEC@ + +# The library that programs using TCL must link against. +# +LIBTCL = @TCL_LIB_SPEC@ @TCL_LIBS@ + +# Compiler options needed for programs that use the readline() library. +# +READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@ + +# The library that programs using readline() must link against. +# +LIBREADLINE = @TARGET_READLINE_LIBS@ + +# Should the database engine be compiled threadsafe +# +TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@ + +# The pthreads library if needed +# +LIBPTHREAD=@TARGET_THREAD_LIB@ + +# Do threads override each others locks by default (1), or do we test (-1) +# +TCC += -DSQLITE_THREAD_OVERRIDE_LOCK=@THREADSOVERRIDELOCKS@ + +# The fdatasync library +TLIBS = @LIBS@ + +# Flags controlling use of the in memory btree implementation +# +# 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. +# +TEMP_STORE = -DTEMP_STORE=@TEMP_STORE@ + +# Version numbers and release number for the SQLite being compiled. +# +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +RELEASE = @RELEASE@ + +# Filename extensions +# +BEXE = @BUILD_EXEEXT@ +TEXE = @TARGET_EXEEXT@ + +# The following variable is "1" if the configure script was able to locate +# the tclConfig.sh file. It is an empty string otherwise. When this +# variable is "1", the TCL extension library (libtclsqlite3.so) is built +# and installed. +# +HAVE_TCL = @HAVE_TCL@ + +# The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib" +# +SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@ + +# The directory into which to store package information for + +# Some standard variables and programs +# +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +INSTALL = @INSTALL@ +LIBTOOL = ./libtool +ALLOWRELEASE = @ALLOWRELEASE@ + +# libtool compile/link/install +LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) +LTLINK = $(LIBTOOL) --mode=link $(TCC) @LDFLAGS@ +LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) + +# nawk compatible awk. +NAWK = @AWK@ + +# You should not have to change anything below this line +############################################################################### +TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1 + +# Object files for the SQLite library. +# +LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btmutex.lo btree.lo build.lo \ + callback.lo complete.lo date.lo \ + delete.lo expr.lo fault.lo func.lo \ + hash.lo journal.lo insert.lo loadext.lo \ + main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mutex.lo \ + mutex_os2.lo mutex_unix.lo mutex_w32.lo \ + opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ + pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ + select.lo table.lo tokenize.lo trigger.lo update.lo \ + util.lo vacuum.lo \ + vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \ + where.lo utf.lo legacy.lo vtab.lo + +# 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/btmutex.c \ + $(TOP)/src/btree.c \ + $(TOP)/src/btree.h \ + $(TOP)/src/build.c \ + $(TOP)/src/callback.c \ + $(TOP)/src/complete.c \ + $(TOP)/src/date.c \ + $(TOP)/src/delete.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/fault.c \ + $(TOP)/src/func.c \ + $(TOP)/src/hash.c \ + $(TOP)/src/hash.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/mem1.c \ + $(TOP)/src/mem2.c \ + $(TOP)/src/mem3.c \ + $(TOP)/src/mem4.c \ + $(TOP)/src/mutex.c \ + $(TOP)/src/mutex_os2.c \ + $(TOP)/src/mutex_unix.c \ + $(TOP)/src/mutex_w32.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_unix.c \ + $(TOP)/src/os_win.c \ + $(TOP)/src/os_os2.c \ + $(TOP)/src/pager.c \ + $(TOP)/src/pager.h \ + $(TOP)/src/parse.y \ + $(TOP)/src/pragma.c \ + $(TOP)/src/prepare.c \ + $(TOP)/src/printf.c \ + $(TOP)/src/random.c \ + $(TOP)/src/select.c \ + $(TOP)/src/shell.c \ + $(TOP)/src/sqlite.h.in \ + $(TOP)/src/sqliteInt.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/vdbefifo.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vtab.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 + + +# Source code to the test files. +# +TESTSRC = \ + $(TOP)/src/attach.c \ + $(TOP)/src/btree.c \ + $(TOP)/src/build.c \ + $(TOP)/src/date.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/func.c \ + $(TOP)/src/insert.c \ + $(TOP)/src/malloc.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_os2.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/select.c \ + $(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_btree.c \ + $(TOP)/src/test_config.c \ + $(TOP)/src/test_devsym.c \ + $(TOP)/src/test_hexio.c \ + $(TOP)/src/test_malloc.c \ + $(TOP)/src/test_md5.c \ + $(TOP)/src/test_onefile.c \ + $(TOP)/src/test_schema.c \ + $(TOP)/src/test_server.c \ + $(TOP)/src/test_tclvar.c \ + $(TOP)/src/test_thread.c \ + $(TOP)/src/tokenize.c \ + $(TOP)/src/utf.c \ + $(TOP)/src/util.c \ + $(TOP)/src/vdbe.c \ + $(TOP)/src/vdbeapi.c \ + $(TOP)/src/vdbeaux.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/where.c \ + parse.c + +# Header files used by all library source files. +# +HDR = \ + sqlite3.h \ + $(TOP)/src/btree.h \ + $(TOP)/src/btreeInt.h \ + $(TOP)/src/hash.h \ + $(TOP)/src/sqliteLimit.h \ + $(TOP)/src/mutex.h \ + opcodes.h \ + $(TOP)/src/os.h \ + $(TOP)/src/os_common.h \ + $(TOP)/src/sqlite3ext.h \ + $(TOP)/src/sqliteInt.h \ + $(TOP)/src/vdbe.h \ + parse.h + +# Header files used by extensions +# +HDR += \ + $(TOP)/ext/fts1/fts1.h \ + $(TOP)/ext/fts1/fts1_hash.h \ + $(TOP)/ext/fts1/fts1_tokenizer.h + +# Header files used by the VDBE submodule +# +VDBEHDR = \ + $(HDR) \ + $(TOP)/src/vdbeInt.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.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la) + +Makefile: $(TOP)/Makefile.in + ./config.status + +# Generate the file "last_change" which contains the date of change +# of the most recently modified source code file +# +last_change: $(SRC) + cat $(SRC) | grep '$$Id: ' | sort -k 5 | tail -1 \ + | $(NAWK) '{print $$5,$$6}' >last_change + +libsqlite3.la: $(LIBOBJ) + $(LTLINK) -o libsqlite3.la $(LIBOBJ) $(LIBPTHREAD) \ + ${ALLOWRELEASE} -rpath $(libdir) -version-info "8:6:8" + +libtclsqlite3.la: tclsqlite.lo libsqlite3.la + $(LTLINK) -o libtclsqlite3.la tclsqlite.lo \ + $(LIBOBJ) @TCL_STUB_LIB_SPEC@ $(LIBPTHREAD) \ + -rpath $(libdir)/sqlite \ + -version-info "8:6:8" + +sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h + $(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \ + -o $@ $(TOP)/src/shell.c libsqlite3.la \ + $(LIBREADLINE) $(TLIBS) + +# 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) parse.c opcodes.c keywordhash.h $(VDBEHDR) + rm -rf tsrc + mkdir -p tsrc + cp $(SRC) $(VDBEHDR) tsrc + rm tsrc/sqlite.h.in tsrc/parse.y + cp parse.c opcodes.c keywordhash.h tsrc + +sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl + tclsh $(TOP)/tool/mksqlite3c.tcl + +# Rules to build the LEMON compiler generator +# +lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c + $(BCC) -o lemon$(BEXE) $(TOP)/tool/lemon.c + cp $(TOP)/tool/lempar.c . + + +# Rules to build individual files +# +alter.lo: $(TOP)/src/alter.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/alter.c + +analyze.lo: $(TOP)/src/analyze.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/analyze.c + +attach.lo: $(TOP)/src/attach.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/attach.c + +auth.lo: $(TOP)/src/auth.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/auth.c + +btmutex.lo: $(TOP)/src/btmutex.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/btmutex.c + +btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h + $(LTCOMPILE) -c $(TOP)/src/btree.c + +build.lo: $(TOP)/src/build.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/build.c + +callback.lo: $(TOP)/src/callback.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/callback.c + +complete.lo: $(TOP)/src/complete.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/complete.c + +date.lo: $(TOP)/src/date.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/date.c + +delete.lo: $(TOP)/src/delete.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/delete.c + +expr.lo: $(TOP)/src/expr.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/expr.c + +fault.lo: $(TOP)/src/fault.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/fault.c + +func.lo: $(TOP)/src/func.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/func.c + +hash.lo: $(TOP)/src/hash.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/hash.c + +insert.lo: $(TOP)/src/insert.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/insert.c + +journal.lo: $(TOP)/src/journal.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/journal.c + +legacy.lo: $(TOP)/src/legacy.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/legacy.c + +loadext.lo: $(TOP)/src/loadext.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/loadext.c + +main.lo: $(TOP)/src/main.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c + +malloc.lo: $(TOP)/src/malloc.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c + +mem1.lo: $(TOP)/src/mem1.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c + +mem2.lo: $(TOP)/src/mem2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem2.c + +mem3.lo: $(TOP)/src/mem3.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c + +mem4.lo: $(TOP)/src/mem4.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem4.c + +mutex.lo: $(TOP)/src/mutex.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c + +mutex_os2.lo: $(TOP)/src/mutex_os2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_os2.c + +mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c + +mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c + +pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h + $(LTCOMPILE) -c $(TOP)/src/pager.c + +opcodes.lo: opcodes.c + $(LTCOMPILE) -c opcodes.c + +opcodes.c: opcodes.h $(TOP)/mkopcodec.awk + sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >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 + +os.lo: $(TOP)/src/os.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os.c + +os_unix.lo: $(TOP)/src/os_unix.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_unix.c + +os_win.lo: $(TOP)/src/os_win.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_win.c + +os_os2.lo: $(TOP)/src/os_os2.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_os2.c + +parse.lo: parse.c $(HDR) + $(LTCOMPILE) -c parse.c + +parse.h: parse.c + +parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk + cp $(TOP)/src/parse.y . + ./lemon$(BEXE) $(OPTS) parse.y + mv parse.h parse.h.temp + $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h + +pragma.lo: $(TOP)/src/pragma.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/pragma.c + +prepare.lo: $(TOP)/src/prepare.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/prepare.c + +printf.lo: $(TOP)/src/printf.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/printf.c + +random.lo: $(TOP)/src/random.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/random.c + +select.lo: $(TOP)/src/select.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/select.c + +sqlite3.h: $(TOP)/src/sqlite.h.in + sed -e s/--VERS--/$(RELEASE)/ $(TOP)/src/sqlite.h.in | \ + sed -e s/--VERSION-NUMBER--/$(VERSION_NUMBER)/ >sqlite3.h + +table.lo: $(TOP)/src/table.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/table.c + +tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/tclsqlite.c + +tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR) + $(LTCOMPILE) -c $(TOP)/src/tokenize.c + +keywordhash.h: $(TOP)/tool/mkkeywordhash.c + $(BCC) -o mkkeywordhash$(BEXE) $(OPTS) $(TOP)/tool/mkkeywordhash.c + ./mkkeywordhash$(BEXE) >keywordhash.h + +trigger.lo: $(TOP)/src/trigger.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/trigger.c + +update.lo: $(TOP)/src/update.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/update.c + +utf.lo: $(TOP)/src/utf.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/utf.c + +util.lo: $(TOP)/src/util.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/util.c + +vacuum.lo: $(TOP)/src/vacuum.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/vacuum.c + +vdbe.lo: $(TOP)/src/vdbe.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbe.c + +vdbeapi.lo: $(TOP)/src/vdbeapi.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeapi.c + +vdbeaux.lo: $(TOP)/src/vdbeaux.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeaux.c + +vdbeblob.lo: $(TOP)/src/vdbeblob.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeblob.c + +vdbefifo.lo: $(TOP)/src/vdbefifo.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbefifo.c + +vdbemem.lo: $(TOP)/src/vdbemem.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbemem.c + +vtab.lo: $(TOP)/src/vtab.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vtab.c + +where.lo: $(TOP)/src/where.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/where.c + +tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -DTCL_USE_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite3: tclsqlite-shell.lo libsqlite3.la + $(LTLINK) -o tclsqlite3 tclsqlite-shell.lo \ + libsqlite3.la $(LIBTCL) + +testfixture$(TEXE): $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) + $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \ + -DSQLITE_NO_SYNC=1 $(TEMP_STORE) \ + -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libsqlite3.la $(LIBTCL) + + +fulltest: testfixture$(TEXE) sqlite3$(TEXE) + ./testfixture $(TOP)/test/all.test + +test: testfixture$(TEXE) sqlite3$(TEXE) + ./testfixture $(TOP)/test/quick.test + +sqlite3_analyzer$(TEXE): $(TOP)/src/tclsqlite.c libtclsqlite3.la \ + $(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 + $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 $(TEMP_STORE)\ + -o sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libtclsqlite3.la $(LIBTCL) + + +install: sqlite3$(BEXE) libsqlite3.la sqlite3.h ${HAVE_TCL:1=tcl_install} + $(INSTALL) -d $(DESTDIR)$(libdir) + $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) + $(INSTALL) -d $(DESTDIR)$(exec_prefix)/bin + $(LTINSTALL) sqlite3$(BEXE) $(DESTDIR)$(exec_prefix)/bin + $(INSTALL) -d $(DESTDIR)$(prefix)/include + $(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(prefix)/include + $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(prefix)/include + $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig; + $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(libdir)/pkgconfig; + +tcl_install: libtclsqlite3.la + tclsh $(TOP)/tclinstaller.tcl $(VERSION) + +clean: + rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la + rm -f sqlite3.h opcodes.* + rm -rf .libs .deps + rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz + rm -f mkkeywordhash$(BEXE) keywordhash.h + rm -f $(PUBLISH) + rm -f *.da *.bb *.bbg gmon.out + rm -f testfixture$(TEXE) test.db + rm -f common.tcl + rm -f sqlite3.dll sqlite3.lib sqlite3.def + +distclean: clean + rm -f config.log config.status libtool Makefile config.h sqlite3.pc + +# +# Windows section +# +dll: sqlite3.dll + +REAL_LIBOBJ = $(LIBOBJ:%.lo=.libs/%.o) + +$(REAL_LIBOBJ): $(LIBOBJ) + +sqlite3.def: $(REAL_LIBOBJ) + echo 'EXPORTS' >sqlite3.def + nm $(REAL_LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \ + | sed 's/^.* _//' >>sqlite3.def + +sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def + $(TCC) -shared -o sqlite3.dll sqlite3.def \ + -Wl,"--strip-all" $(REAL_LIBOBJ) diff --git a/client/src/thirdparty/sqlite-3.4.2/Makefile.linux-gcc b/client/src/thirdparty/sqlite-3.4.2/Makefile.linux-gcc new file mode 100644 index 0000000..2bb6184 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/Makefile.linux-gcc @@ -0,0 +1,128 @@ +#!/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 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 +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 = /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 +RANLIB = ranlib +#RANLIB = /opt/mingw/bin/i386-mingw32-ranlib + +MKSHLIB = gcc -shared +SO = so +SHPREFIX = lib +# 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.4linux +#TCL_FLAGS = -I/home/drh/tcltk/8.4win -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.4linux/libtcl8.4g.a -lm -ldl +#LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.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/client/src/thirdparty/sqlite-3.4.2/Makefile.org b/client/src/thirdparty/sqlite-3.4.2/Makefile.org new file mode 100644 index 0000000..5efb24a --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/Makefile.org @@ -0,0 +1,622 @@ +#!/usr/make +# +# Makefile for SQLITE +# +# This makefile is suppose to be configured automatically using the +# autoconf. But if that does not work for you, you can configure +# the makefile manually. Just set the parameters below to values that +# work well for your system. +# +# If the configure script does not work out-of-the-box, you might +# be able to get it to work by giving it some hints. See the comment +# at the beginning of configure.in for additional information. +# + +# The toplevel directory of the source tree. This is the directory +# that contains this "Makefile.in" and the "configure.in" script. +# +TOP = @srcdir@ + +# C Compiler and options for use in building executables that +# will run on the platform that is doing the build. +# +BCC = @BUILD_CC@ @BUILD_CFLAGS@ + +# C Compile 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.) +# +TCC = @CC@ @CFLAGS@ -I. -I${TOP}/src + +# 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. +# +TCC += @TARGET_DEBUG@ @XTHREADCONNECT@ + +# Compiler options needed for programs that use the TCL library. +# +TCC += @TCL_INCLUDE_SPEC@ + +# The library that programs using TCL must link against. +# +LIBTCL = @TCL_LIB_SPEC@ @TCL_LIBS@ + +# Compiler options needed for programs that use the readline() library. +# +READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@ + +# The library that programs using readline() must link against. +# +LIBREADLINE = @TARGET_READLINE_LIBS@ + +# Should the database engine be compiled threadsafe +# +TCC += -DSQLITE_THREADSAFE=@SQLITE_THREADSAFE@ + +# The pthreads library if needed +# +LIBPTHREAD=@TARGET_THREAD_LIB@ + +# Do threads override each others locks by default (1), or do we test (-1) +# +TCC += -DSQLITE_THREAD_OVERRIDE_LOCK=@THREADSOVERRIDELOCKS@ + +# The fdatasync library +TLIBS = @LIBS@ + +# Flags controlling use of the in memory btree implementation +# +# 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. +# +TEMP_STORE = -DTEMP_STORE=@TEMP_STORE@ + +# Version numbers and release number for the SQLite being compiled. +# +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +RELEASE = @RELEASE@ + +# Filename extensions +# +BEXE = @BUILD_EXEEXT@ +TEXE = @TARGET_EXEEXT@ + +# The following variable is "1" if the configure script was able to locate +# the tclConfig.sh file. It is an empty string otherwise. When this +# variable is "1", the TCL extension library (libtclsqlite3.so) is built +# and installed. +# +HAVE_TCL = @HAVE_TCL@ + +# The suffix used on shared libraries. Ex: ".dll", ".so", ".dylib" +# +SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@ + +# The directory into which to store package information for + +# Some standard variables and programs +# +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +INSTALL = @INSTALL@ +LIBTOOL = ./libtool +ALLOWRELEASE = @ALLOWRELEASE@ + +# libtool compile/link/install +LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(TCC) +LTLINK = $(LIBTOOL) --mode=link $(TCC) @LDFLAGS@ +LTINSTALL = $(LIBTOOL) --mode=install $(INSTALL) + +# nawk compatible awk. +NAWK = @AWK@ + +# You should not have to change anything below this line +############################################################################### +TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1 + +# Object files for the SQLite library. +# +LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btmutex.lo btree.lo build.lo \ + callback.lo complete.lo date.lo \ + delete.lo expr.lo func.lo hash.lo journal.lo insert.lo loadext.lo \ + main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mutex.lo \ + mutex_os2.lo mutex_unix.lo mutex_w32.lo \ + opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \ + pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \ + select.lo table.lo tokenize.lo trigger.lo update.lo \ + util.lo vacuum.lo \ + vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbefifo.lo vdbemem.lo \ + where.lo utf.lo legacy.lo vtab.lo + +# 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/btmutex.c \ + $(TOP)/src/btree.c \ + $(TOP)/src/btree.h \ + $(TOP)/src/build.c \ + $(TOP)/src/callback.c \ + $(TOP)/src/complete.c \ + $(TOP)/src/date.c \ + $(TOP)/src/delete.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/func.c \ + $(TOP)/src/hash.c \ + $(TOP)/src/hash.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/mem1.c \ + $(TOP)/src/mem2.c \ + $(TOP)/src/mem3.c \ + $(TOP)/src/mem4.c \ + $(TOP)/src/mutex.c \ + $(TOP)/src/mutex_os2.c \ + $(TOP)/src/mutex_unix.c \ + $(TOP)/src/mutex_w32.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_unix.c \ + $(TOP)/src/os_win.c \ + $(TOP)/src/os_os2.c \ + $(TOP)/src/pager.c \ + $(TOP)/src/pager.h \ + $(TOP)/src/parse.y \ + $(TOP)/src/pragma.c \ + $(TOP)/src/prepare.c \ + $(TOP)/src/printf.c \ + $(TOP)/src/random.c \ + $(TOP)/src/select.c \ + $(TOP)/src/shell.c \ + $(TOP)/src/sqlite.h.in \ + $(TOP)/src/sqliteInt.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/vdbefifo.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vtab.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 + + +# Source code to the test files. +# +TESTSRC = \ + $(TOP)/src/attach.c \ + $(TOP)/src/btree.c \ + $(TOP)/src/build.c \ + $(TOP)/src/date.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/func.c \ + $(TOP)/src/insert.c \ + $(TOP)/src/malloc.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os_os2.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/select.c \ + $(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_btree.c \ + $(TOP)/src/test_config.c \ + $(TOP)/src/test_hexio.c \ + $(TOP)/src/test_malloc.c \ + $(TOP)/src/test_md5.c \ + $(TOP)/src/test_onefile.c \ + $(TOP)/src/test_schema.c \ + $(TOP)/src/test_server.c \ + $(TOP)/src/test_tclvar.c \ + $(TOP)/src/test_thread.c \ + $(TOP)/src/tokenize.c \ + $(TOP)/src/utf.c \ + $(TOP)/src/util.c \ + $(TOP)/src/vdbe.c \ + $(TOP)/src/vdbeapi.c \ + $(TOP)/src/vdbeaux.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/where.c \ + parse.c + +# Header files used by all library source files. +# +HDR = \ + sqlite3.h \ + $(TOP)/src/btree.h \ + $(TOP)/src/btreeInt.h \ + $(TOP)/src/hash.h \ + $(TOP)/src/sqliteLimit.h \ + $(TOP)/src/mutex.h \ + opcodes.h \ + $(TOP)/src/os.h \ + $(TOP)/src/os_common.h \ + $(TOP)/src/sqlite3ext.h \ + $(TOP)/src/sqliteInt.h \ + $(TOP)/src/vdbe.h \ + parse.h + +# Header files used by extensions +# +HDR += \ + $(TOP)/ext/fts1/fts1.h \ + $(TOP)/ext/fts1/fts1_hash.h \ + $(TOP)/ext/fts1/fts1_tokenizer.h + +# Header files used by the VDBE submodule +# +VDBEHDR = \ + $(HDR) \ + $(TOP)/src/vdbeInt.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.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la) + +Makefile: $(TOP)/Makefile.in + ./config.status + +# Generate the file "last_change" which contains the date of change +# of the most recently modified source code file +# +last_change: $(SRC) + cat $(SRC) | grep '$$Id: ' | sort -k 5 | tail -1 \ + | $(NAWK) '{print $$5,$$6}' >last_change + +libsqlite3.la: $(LIBOBJ) + $(LTLINK) -o libsqlite3.la $(LIBOBJ) $(LIBPTHREAD) \ + ${ALLOWRELEASE} -rpath $(libdir) -version-info "8:6:8" + +libtclsqlite3.la: tclsqlite.lo libsqlite3.la + $(LTLINK) -o libtclsqlite3.la tclsqlite.lo \ + $(LIBOBJ) @TCL_STUB_LIB_SPEC@ $(LIBPTHREAD) \ + -rpath $(libdir)/sqlite \ + -version-info "8:6:8" + +sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h + $(LTLINK) $(READLINE_FLAGS) $(LIBPTHREAD) \ + -o $@ $(TOP)/src/shell.c libsqlite3.la \ + $(LIBREADLINE) $(TLIBS) + +# 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) parse.c opcodes.c keywordhash.h $(VDBEHDR) + rm -rf tsrc + mkdir -p tsrc + cp $(SRC) $(VDBEHDR) tsrc + rm tsrc/sqlite.h.in tsrc/parse.y + cp parse.c opcodes.c keywordhash.h tsrc + +sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl + tclsh $(TOP)/tool/mksqlite3c.tcl + +# Rules to build the LEMON compiler generator +# +lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c + $(BCC) -o lemon$(BEXE) $(TOP)/tool/lemon.c + cp $(TOP)/tool/lempar.c . + + +# Rules to build individual files +# +alter.lo: $(TOP)/src/alter.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/alter.c + +analyze.lo: $(TOP)/src/analyze.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/analyze.c + +attach.lo: $(TOP)/src/attach.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/attach.c + +auth.lo: $(TOP)/src/auth.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/auth.c + +btmutex.lo: $(TOP)/src/btmutex.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/btmutex.c + +btree.lo: $(TOP)/src/btree.c $(HDR) $(TOP)/src/pager.h + $(LTCOMPILE) -c $(TOP)/src/btree.c + +build.lo: $(TOP)/src/build.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/build.c + +callback.lo: $(TOP)/src/callback.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/callback.c + +complete.lo: $(TOP)/src/complete.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/complete.c + +date.lo: $(TOP)/src/date.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/date.c + +delete.lo: $(TOP)/src/delete.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/delete.c + +expr.lo: $(TOP)/src/expr.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/expr.c + +func.lo: $(TOP)/src/func.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/func.c + +hash.lo: $(TOP)/src/hash.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/hash.c + +insert.lo: $(TOP)/src/insert.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/insert.c + +journal.lo: $(TOP)/src/journal.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/journal.c + +legacy.lo: $(TOP)/src/legacy.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/legacy.c + +loadext.lo: $(TOP)/src/loadext.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/loadext.c + +main.lo: $(TOP)/src/main.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c + +malloc.lo: $(TOP)/src/malloc.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c + +mem1.lo: $(TOP)/src/mem1.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem1.c + +mem2.lo: $(TOP)/src/mem2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem2.c + +mem3.lo: $(TOP)/src/mem3.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem3.c + +mem4.lo: $(TOP)/src/mem4.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mem4.c + +mutex.lo: $(TOP)/src/mutex.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex.c + +mutex_os2.lo: $(TOP)/src/mutex_os2.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_os2.c + +mutex_unix.lo: $(TOP)/src/mutex_unix.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_unix.c + +mutex_w32.lo: $(TOP)/src/mutex_w32.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/mutex_w32.c + +pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h + $(LTCOMPILE) -c $(TOP)/src/pager.c + +opcodes.lo: opcodes.c + $(LTCOMPILE) -c opcodes.c + +opcodes.c: opcodes.h $(TOP)/mkopcodec.awk + sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >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 + +os.lo: $(TOP)/src/os.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os.c + +os_unix.lo: $(TOP)/src/os_unix.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_unix.c + +os_win.lo: $(TOP)/src/os_win.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_win.c + +os_os2.lo: $(TOP)/src/os_os2.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/os_os2.c + +parse.lo: parse.c $(HDR) + $(LTCOMPILE) -c parse.c + +parse.h: parse.c + +parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/addopcodes.awk + cp $(TOP)/src/parse.y . + ./lemon$(BEXE) $(OPTS) parse.y + mv parse.h parse.h.temp + $(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h + +pragma.lo: $(TOP)/src/pragma.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/pragma.c + +prepare.lo: $(TOP)/src/prepare.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/prepare.c + +printf.lo: $(TOP)/src/printf.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/printf.c + +random.lo: $(TOP)/src/random.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/random.c + +select.lo: $(TOP)/src/select.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/select.c + +sqlite3.h: $(TOP)/src/sqlite.h.in + sed -e s/--VERS--/$(RELEASE)/ $(TOP)/src/sqlite.h.in | \ + sed -e s/--VERSION-NUMBER--/$(VERSION_NUMBER)/ >sqlite3.h + +table.lo: $(TOP)/src/table.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/table.c + +tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/tclsqlite.c + +tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR) + $(LTCOMPILE) -c $(TOP)/src/tokenize.c + +keywordhash.h: $(TOP)/tool/mkkeywordhash.c + $(BCC) -o mkkeywordhash$(BEXE) $(OPTS) $(TOP)/tool/mkkeywordhash.c + ./mkkeywordhash$(BEXE) >keywordhash.h + +trigger.lo: $(TOP)/src/trigger.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/trigger.c + +update.lo: $(TOP)/src/update.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/update.c + +utf.lo: $(TOP)/src/utf.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/utf.c + +util.lo: $(TOP)/src/util.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/util.c + +vacuum.lo: $(TOP)/src/vacuum.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/vacuum.c + +vdbe.lo: $(TOP)/src/vdbe.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbe.c + +vdbeapi.lo: $(TOP)/src/vdbeapi.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeapi.c + +vdbeaux.lo: $(TOP)/src/vdbeaux.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeaux.c + +vdbeblob.lo: $(TOP)/src/vdbeblob.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbeblob.c + +vdbefifo.lo: $(TOP)/src/vdbefifo.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbefifo.c + +vdbemem.lo: $(TOP)/src/vdbemem.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vdbemem.c + +vtab.lo: $(TOP)/src/vtab.c $(VDBEHDR) + $(LTCOMPILE) -c $(TOP)/src/vtab.c + +where.lo: $(TOP)/src/where.c $(HDR) + $(LTCOMPILE) -c $(TOP)/src/where.c + +tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR) + $(LTCOMPILE) -DTCL_USE_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c + +tclsqlite3: tclsqlite-shell.lo libsqlite3.la + $(LTLINK) -o tclsqlite3 tclsqlite-shell.lo \ + libsqlite3.la $(LIBTCL) + +testfixture$(TEXE): $(TOP)/src/tclsqlite.c libsqlite3.la $(TESTSRC) + $(LTLINK) -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 \ + -DSQLITE_NO_SYNC=1 $(TEMP_STORE) \ + -o testfixture $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libsqlite3.la $(LIBTCL) + + +fulltest: testfixture$(TEXE) sqlite3$(TEXE) + ./testfixture $(TOP)/test/all.test + +test: testfixture$(TEXE) sqlite3$(TEXE) + ./testfixture $(TOP)/test/quick.test + +sqlite3_analyzer$(TEXE): $(TOP)/src/tclsqlite.c libtclsqlite3.la \ + $(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 + $(LTLINK) -DTCLSH=2 -DSQLITE_TEST=1 $(TEMP_STORE)\ + -o sqlite3_analyzer$(EXE) $(TESTSRC) $(TOP)/src/tclsqlite.c \ + libtclsqlite3.la $(LIBTCL) + + +install: sqlite3$(BEXE) libsqlite3.la sqlite3.h ${HAVE_TCL:1=tcl_install} + $(INSTALL) -d $(DESTDIR)$(libdir) + $(LTINSTALL) libsqlite3.la $(DESTDIR)$(libdir) + $(INSTALL) -d $(DESTDIR)$(exec_prefix)/bin + $(LTINSTALL) sqlite3$(BEXE) $(DESTDIR)$(exec_prefix)/bin + $(INSTALL) -d $(DESTDIR)$(prefix)/include + $(INSTALL) -m 0644 sqlite3.h $(DESTDIR)$(prefix)/include + $(INSTALL) -m 0644 $(TOP)/src/sqlite3ext.h $(DESTDIR)$(prefix)/include + $(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig; + $(INSTALL) -m 0644 sqlite3.pc $(DESTDIR)$(libdir)/pkgconfig; + +tcl_install: libtclsqlite3.la + tclsh $(TOP)/tclinstaller.tcl $(VERSION) + +clean: + rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la + rm -f sqlite3.h opcodes.* + rm -rf .libs .deps + rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz + rm -f mkkeywordhash$(BEXE) keywordhash.h + rm -f $(PUBLISH) + rm -f *.da *.bb *.bbg gmon.out + rm -f testfixture$(TEXE) test.db + rm -f common.tcl + rm -f sqlite3.dll sqlite3.lib sqlite3.def + +distclean: clean + rm -f config.log config.status libtool Makefile config.h sqlite3.pc + +# +# Windows section +# +dll: sqlite3.dll + +REAL_LIBOBJ = $(LIBOBJ:%.lo=.libs/%.o) + +$(REAL_LIBOBJ): $(LIBOBJ) + +sqlite3.def: $(REAL_LIBOBJ) + echo 'EXPORTS' >sqlite3.def + nm $(REAL_LIBOBJ) | grep ' T ' | grep ' _sqlite3_' \ + | sed 's/^.* _//' >>sqlite3.def + +sqlite3.dll: $(REAL_LIBOBJ) sqlite3.def + $(TCC) -shared -o sqlite3.dll sqlite3.def \ + -Wl,"--strip-all" $(REAL_LIBOBJ) diff --git a/client/src/thirdparty/sqlite-3.4.2/README b/client/src/thirdparty/sqlite-3.4.2/README new file mode 100644 index 0000000..6e4f392 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/README @@ -0,0 +1,35 @@ +This directory contains source code to + + SQLite: An Embeddable SQL Database Engine + +To compile the project, first create a directory in which to place +the build products. It is recommended, but not required, that the +build directory be separate from the source directory. Cd into the +build directory and then from the build directory run the configure +script found at the root of the source tree. Then run "make". + +For example: + + tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" + mkdir bld ;# Build will occur in a sibling directory + cd bld ;# Change to the build directory + ../sqlite/configure ;# Run the configure script + make ;# Run the makefile. + make install ;# (Optional) Install the build products + +The configure script uses autoconf 2.50 and libtool. If the configure +script does not work out for you, there is a generic makefile named +"Makefile.linux-gcc" in the top directory of the source tree that you +can copy and edit to suite your needs. Comments on the generic makefile +show what changes are needed. + +The linux binaries on the website are created using the generic makefile, +not the configure script. The configure script is unmaintained. (You +can volunteer to take over maintenance of the configure script, if you want!) +The windows binaries on the website are created using MinGW32 configured +as a cross-compiler running under Linux. For details, see the ./publish.sh +script at the top-level of the source tree. + +Contacts: + + http://www.sqlite.org/ diff --git a/client/src/thirdparty/sqlite-3.4.2/VERSION b/client/src/thirdparty/sqlite-3.4.2/VERSION new file mode 100644 index 0000000..c492825 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/VERSION @@ -0,0 +1 @@ +3.5.6 diff --git a/client/src/thirdparty/sqlite-3.4.2/aclocal.m4 b/client/src/thirdparty/sqlite-3.4.2/aclocal.m4 new file mode 100644 index 0000000..27b6c66 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/aclocal.m4 @@ -0,0 +1,6470 @@ +# generated automatically by aclocal 1.10 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +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 "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. +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 to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Check if we have a version mismatch between libtool.m4 and ltmain.sh. +# +# Note: This should be in AC_LIBTOOL_SETUP, _after_ $ltmain have been defined. +# We also should do it _before_ AC_LIBTOOL_LANG_C_CONFIG that actually +# calls AC_LIBTOOL_CONFIG and creates libtool. +# +_LT_VERSION_CHECK + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_VERSION_CHECK +# ----------------- +AC_DEFUN([_LT_VERSION_CHECK], +[AC_MSG_CHECKING([for correct ltmain.sh version]) +if test "x$ltmain" = "x" ; then + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + +*** @<:@Gentoo@:>@ sanity check failed! *** +*** \$ltmain is not defined, please check the patch for consistency! *** +]) +fi +gentoo_lt_version="1.5.22" +gentoo_ltmain_version=`sed -n '/^[[ ]]*VERSION=/{s/^[[ ]]*VERSION=//;p;q;}' "$ltmain"` +if test "x$gentoo_lt_version" != "x$gentoo_ltmain_version" ; then + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + +*** @<:@Gentoo@:>@ sanity check failed! *** +*** libtool.m4 and ltmain.sh have a version mismatch! *** +*** (libtool.m4 = $gentoo_lt_version, ltmain.sh = $gentoo_ltmain_version) *** + +Please run: + + libtoolize --copy --force + +if appropriate, please contact the maintainer of this +package (or your distribution) for help. +]) +else + AC_MSG_RESULT(yes) +fi +])# _LT_VERSION_CHECK + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; 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-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${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 </dev/null 2>&1 && unset CDPATH + +if test -z "$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 && + echo_test_string=`eval $cmd` && + (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. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +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 which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + 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" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + 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 "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 + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$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>&AS_MESSAGE_LOG_FD + $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 + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + 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; + ;; + + 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` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + 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` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + 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 + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # 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. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + 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 "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + 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 "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_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != 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 "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +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" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + 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 ';' >/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. + 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 +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + 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' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + 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}' + 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 + # 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 + : + else + can_build_shared=no + fi + ;; + esac + # 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. + 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}' + 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' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + 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=`$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' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + 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' + 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" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + 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'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + 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="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + 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}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; 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 -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + 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 + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${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`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + 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' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # 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} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + 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*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + 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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + 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 "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + 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' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + 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' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + 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' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + 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}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + 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}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + 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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # 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 + + # 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)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + 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' + 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' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + 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 + ;; + +nto-qnx*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # 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 + 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' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + 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}' + 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" + ;; + +solaris*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + 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 "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + 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) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + 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=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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + 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 + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + 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," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + 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 +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + 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" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-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` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + 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" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + 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" + # 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 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + 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]) 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_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +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)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +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 +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + 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 + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + 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 + # Check to see if the nm accepts a BSD-compat flag. + # 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 + 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 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +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 "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + 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="" + else + 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 + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = 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` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + 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 "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + 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. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$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. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${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. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$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 + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $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... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='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 -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${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. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='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' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # 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. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 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 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# 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. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# 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 + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# 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. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +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 in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# 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_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# 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 "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # 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) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +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 + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # 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_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # 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_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # 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_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # 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'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # 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 + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # 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 "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + 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 + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${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 + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** 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 modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$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 + _LT_AC_TAGVAR(archive_cmds, $1)='$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... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='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 + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${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. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='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' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${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*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${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' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** 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 +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + 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="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$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 + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + 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` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + 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 "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + 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. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$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. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${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. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$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 + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=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. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=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 + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$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 + _LT_AC_TAGVAR(archive_cmds, $1)='$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 + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$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*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$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' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$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' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + 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. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # 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. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # 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. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) + diff --git a/client/src/thirdparty/sqlite-3.4.2/addopcodes.awk b/client/src/thirdparty/sqlite-3.4.2/addopcodes.awk new file mode 100644 index 0000000..b806b1d --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/addopcodes.awk @@ -0,0 +1,32 @@ +#!/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+1 + printf "#define TK_%-29s %4d\n", "TO_BLOB", max+2 + printf "#define TK_%-29s %4d\n", "TO_NUMERIC", max+3 + printf "#define TK_%-29s %4d\n", "TO_INT", max+4 + printf "#define TK_%-29s %4d\n", "TO_REAL", max+5 + printf "#define TK_%-29s %4d\n", "END_OF_FILE", max+6 + printf "#define TK_%-29s %4d\n", "ILLEGAL", max+7 + printf "#define TK_%-29s %4d\n", "SPACE", max+8 + printf "#define TK_%-29s %4d\n", "UNCLOSED_STRING", max+9 + printf "#define TK_%-29s %4d\n", "COMMENT", max+10 + printf "#define TK_%-29s %4d\n", "FUNCTION", max+11 + printf "#define TK_%-29s %4d\n", "COLUMN", max+12 + printf "#define TK_%-29s %4d\n", "AGG_FUNCTION", max+13 + printf "#define TK_%-29s %4d\n", "AGG_COLUMN", max+14 + printf "#define TK_%-29s %4d\n", "CONST_FUNC", max+15 +} diff --git a/client/src/thirdparty/sqlite-3.4.2/art/2005osaward.gif b/client/src/thirdparty/sqlite-3.4.2/art/2005osaward.gif new file mode 100644 index 0000000..76da760 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/art/2005osaward.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f625758f8ab9fd01eaa0921c9d6fd92d20aea3312f51fce7160e75a2717c441 +size 3750 diff --git a/client/src/thirdparty/sqlite-3.4.2/art/SQLite.eps b/client/src/thirdparty/sqlite-3.4.2/art/SQLite.eps new file mode 100644 index 0000000000000000000000000000000000000000..1f334ecf7b49ee6e596802d5cf8e208caebb034f GIT binary patch literal 24155 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 DOHLiR literal 0 HcmV?d00001 diff --git a/client/src/thirdparty/sqlite-3.4.2/art/SQLite.gif b/client/src/thirdparty/sqlite-3.4.2/art/SQLite.gif new file mode 100644 index 0000000..4517a50 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/art/SQLite.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1abd4686487a78afd48a991976eff4bfef98187d67d31d11fb9f25ea89d127b0 +size 3062 diff --git a/client/src/thirdparty/sqlite-3.4.2/art/SQLiteLogo3.tiff b/client/src/thirdparty/sqlite-3.4.2/art/SQLiteLogo3.tiff new file mode 100644 index 0000000000000000000000000000000000000000..70b88e78057d7aa046d489e025273ba38d774c1b GIT binary patch literal 85156 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%0A2vxehzOjQ>q9f8Q0p_RnbfbgOQW+j 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 literal 0 HcmV?d00001 diff --git a/client/src/thirdparty/sqlite-3.4.2/art/SQLite_big.gif b/client/src/thirdparty/sqlite-3.4.2/art/SQLite_big.gif new file mode 100644 index 0000000..ac52837 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/art/SQLite_big.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de2d04b2e4cf1a9ba33ed0fa4056ac35bac9a4ddb8b0c8aba6b01be56d06e963 +size 7428 diff --git a/client/src/thirdparty/sqlite-3.4.2/art/nocopy.gif b/client/src/thirdparty/sqlite-3.4.2/art/nocopy.gif new file mode 100644 index 0000000..30544bf --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/art/nocopy.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c3c04918ca0a9cc5b7e6d1f195895fad18a438779da0e7f17814dadafa57f8d +size 3449 diff --git a/client/src/thirdparty/sqlite-3.4.2/art/powered_by_sqlite.gif b/client/src/thirdparty/sqlite-3.4.2/art/powered_by_sqlite.gif new file mode 100644 index 0000000..4511919 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/art/powered_by_sqlite.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a45d4d509612d93c868aab01492fc4ae9b30107a99db0d92ac18686af9a3c69 +size 3391 diff --git a/client/src/thirdparty/sqlite-3.4.2/config.guess b/client/src/thirdparty/sqlite-3.4.2/config.guess new file mode 100644 index 0000000..6960a39 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/config.guess @@ -0,0 +1,1532 @@ +#! /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 Free Software Foundation, +# Inc. + +timestamp='2007-01-15' + +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# 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 to . Submit a context +# diff and a properly formatted 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. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +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 +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 + +if [ "${UNAME_SYSTEM}" = "Linux" ] ; then + eval $set_cc_for_build + cat << EOF > $dummy.c + #include + #ifdef __UCLIBC__ + # ifdef __UCLIBC_CONFIG_VERSION__ + LIBC=uclibc __UCLIBC_CONFIG_VERSION__ + # else + LIBC=uclibc + # endif + #else + LIBC=gnu + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep LIBC= | sed -e 's: ::g'` +fi + +# 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 tupples: *-*-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 __ELF__ >/dev/null + 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'` + exit ;; + 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 ;; + 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:SunOS:5.*:*) + echo i386-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:*:[45]) + 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 __LP64__ >/dev/null + 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:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-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*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[3456]*) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T:Interix*:[3456]* | authenticamd:Interix*:[3456]*) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-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 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + 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 ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + 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-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-${LIBC} + exit ;; + xtensa:Linux:*:*) + echo xtensa-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-${LIBC}" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-${LIBC}aout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-${LIBC}coff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-${LIBC}oldld" + exit ;; + esac + # This should get integrated into the C code below, but now we hack + if [ "$LIBC" != "gnu" ] ; then echo "$TENTATIVE" && exit 0 ; fi + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; 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.0*:*) + 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 i386. + echo i386-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; } ;; + 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.0*:*) + 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 ;; + 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 + 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 ;; + 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 ;; +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/client/src/thirdparty/sqlite-3.4.2/config.log b/client/src/thirdparty/sqlite-3.4.2/config.log new file mode 100644 index 0000000..92a07e9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/config.log @@ -0,0 +1,1565 @@ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by configure, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ configure --disable-tcl --disable-threadsafe + +## --------- ## +## Platform. ## +## --------- ## + +hostname = SCHREIBTISCH_GP +uname -m = pc +uname -r = 5 +uname -s = MS-DOS +uname -v = 50 + +/usr/bin/uname -p = unknown +/bin/uname -X = unknown + +/bin/arch = unknown +/usr/bin/arch -k = unknown +/usr/convex/getsysinfo = unknown +hostinfo = unknown +/bin/machine = unknown +/usr/bin/oslevel = unknown +/bin/universe = unknown + +PATH: /dev/e/usr/local/bin +PATH: /dev/e/usr/local +PATH: /dev/e/djgpp/bin +PATH: /dev/e/djgpp/mwin/src/lib +PATH: /dev/c/progra~1/pcconn~1/ +PATH: /dev/c/windows/system32 +PATH: /dev/c/windows +PATH: /dev/c/windows/system32/wbem +PATH: /dev/d/devkitpro/msys/bin +PATH: /dev/c/progra~1/doxygen/bin +PATH: /dev/c/progra~1/miktex~1.9/miktex/bin/ +PATH: /dev/c/progra~1/tortoi~1/bin +PATH: /dev/e/watcom2/binw + + +## ----------- ## +## Core tests. ## +## ----------- ## + +configure:1407: loading site script e:/djgpp/share/config.site +| #! /bin/sh +| # Version 1.3 by Mark E. Updated April 9, 2001. +| # Modify or replace this file only if you know what your doing. +| +| # Sanity check +| +| if test "x${DJDIR}" = "x"; then +| echo "Your DJGPP installation is not setup correctly. DJDIR is not set." +| exit 1 +| fi +| +| # The root of the DJGPP tree serves as the default prefix. +| # Allow for cases where a top-level Cygnus/Red Hat-style configure script +| # calls Autoconf configure scripts in subdirectories. +| if test "x$ac_default_prefix" = "x/usr/local"; then +| ac_default_prefix="/dev/env/DJDIR" +| fi +| +| # This is required for config.status script to be run, since +| # ./configure runs it by invoking ${CONFIG_SHELL-/bin/sh} +| +| export CONFIG_SHELL='/dev/env/DJDIR/bin/sh.exe' +| export SHELL=${CONFIG_SHELL} +| +| # $INSTALL must be an absolute path name, otherwise config.status +| # will try to prepend ./ and ../ to it when it goes into subdirs. +| +| export INSTALL=${INSTALL='/dev/env/DJDIR/bin/ginstall -c'} +| +| # Help out libtool +| ac_exeext=".exe" +| export lt_cv_sys_max_cmd_len=12288 +| +| # Variables to help DJGPP tools be detected. +| if test -n "${PACKAGE_VERSION}" ; then +| ac_executable_extensions=".exe" +| export PATH_SEPARATOR=';' +| else +| # Settings for Autoconf 2.50 and above. +| export PATH_SEPARATOR=: +| fi +| +| export TEST_FINDS_EXE=Y +| +| # Force the test for 'ln -s' to report no. +| export LN_S="cp -p" +| ac_cv_prog_LN_S="cp -p" +| +configure:1418: loading cache /dev/null +configure:1616: checking build system type +configure:1634: result: i386-pc-msdosdjgpp +configure:1642: checking host system type +configure:1656: result: i386-pc-msdosdjgpp +configure:1710: checking for gcc +configure:1726: found /dev/e/djgpp/bin/gcc +configure:1736: result: gcc +configure:1980: checking for C compiler version +configure:1983: gcc --version &5 +gcc.exe (GCC) 4.5.3 +Copyright (C) 2010 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. + +configure:1986: $? = 0 +configure:1988: gcc -v &5 +Using built-in specs. +COLLECT_GCC=e:/djgpp/bin/gcc.exe +COLLECT_LTO_WRAPPER=e:/djgpp/bin/../libexec/gcc/djgpp/4.53/lto-wrapper.exe +Target: djgpp +Configured with: /v204/gcc-4.53/configure djgpp --prefix=/dev/env/DJDIR --disable-nls --disable-werror --enable-languages=c,c++,fortran,objc,obj-c++,ada +Thread model: single +gcc version 4.5.3 (GCC) +configure:1991: $? = 0 +configure:1993: gcc -V &5 +gcc.exe: '-V' option must have argument +configure:1996: $? = 1 +configure:2019: checking for C compiler default output file name +configure:2022: gcc conftest.c >&5 +configure:2025: $? = 0 +configure:2071: result: a.exe +configure:2076: checking whether the C compiler works +configure:2082: ./a.exe +configure:2085: $? = 0 +configure:2102: result: yes +configure:2109: checking whether we are cross compiling +configure:2111: result: no +configure:2114: checking for suffix of executables +configure:2116: gcc -o conftest.exe conftest.c >&5 +configure:2119: $? = 0 +configure:2144: result: .exe +configure:2150: checking for suffix of object files +configure:2171: gcc -c conftest.c >&5 +configure:2174: $? = 0 +configure:2196: result: o +configure:2200: checking whether we are using the GNU C compiler +configure:2224: gcc -c conftest.c >&5 +configure:2230: $? = 0 +configure:2234: test -z + || test ! -s conftest.err +configure:2237: $? = 0 +configure:2240: test -s conftest.o +configure:2243: $? = 0 +configure:2256: result: yes +configure:2262: checking whether gcc accepts -g +configure:2283: gcc -c -g conftest.c >&5 +configure:2289: $? = 0 +configure:2293: test -z + || test ! -s conftest.err +configure:2296: $? = 0 +configure:2299: test -s conftest.o +configure:2302: $? = 0 +configure:2313: result: yes +configure:2330: checking for gcc option to accept ANSI C +configure:2400: gcc -c -g -O2 conftest.c >&5 +configure:2406: $? = 0 +configure:2410: test -z + || test ! -s conftest.err +configure:2413: $? = 0 +configure:2416: test -s conftest.o +configure:2419: $? = 0 +configure:2437: result: none needed +configure:2455: gcc -c -g -O2 conftest.c >&5 +conftest.c:2:9: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'me' +configure:2461: $? = 1 +configure: failed program was: +| #ifndef __cplusplus +| choke me +| #endif +configure:2594: checking for a sed that does not truncate output +configure:2648: result: /dev/e/djgpp/bin/sed +configure:2651: checking for egrep +configure:2661: result: grep -E +configure:2677: checking for ld used by gcc +configure:2744: result: e:/djgpp/bin/ld.exe +configure:2753: checking if the linker (e:/djgpp/bin/ld.exe) is GNU ld +configure:2768: result: yes +configure:2773: checking for e:/djgpp/bin/ld.exe option to reload object files +configure:2780: result: -r +configure:2798: checking for BSD-compatible nm +configure:2847: result: /dev/e/djgpp/bin/nm -B +configure:2851: checking whether ln -s works +configure:2858: result: no, using ln +configure:2862: checking how to recognise dependent libraries +configure:3038: result: unknown +configure:3275: checking how to run the C preprocessor +configure:3310: gcc -E conftest.c +configure:3316: $? = 0 +configure:3348: gcc -E conftest.c +conftest.c:9:28: fatal error: ac_nonexistent.h: No such file or directory (ENOENT) +compilation terminated. +configure:3354: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| /* end confdefs.h. */ +| #include +configure:3393: result: gcc -E +configure:3417: gcc -E conftest.c +configure:3423: $? = 0 +configure:3455: gcc -E conftest.c +conftest.c:9:28: fatal error: ac_nonexistent.h: No such file or directory (ENOENT) +compilation terminated. +configure:3461: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| /* end confdefs.h. */ +| #include +configure:3505: checking for ANSI C header files +configure:3530: gcc -c -g -O2 conftest.c >&5 +configure:3536: $? = 0 +configure:3540: test -z + || test ! -s conftest.err +configure:3543: $? = 0 +configure:3546: test -s conftest.o +configure:3549: $? = 0 +configure:3635: gcc -o conftest.exe -g -O2 conftest.c >&5 +conftest.c: In function 'main': +conftest.c:26:7: warning: incompatible implicit declaration of built-in function 'exit' +configure:3638: $? = 0 +configure:3640: ./conftest.exe +configure:3643: $? = 0 +configure:3658: result: yes +configure:3682: checking for sys/types.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for sys/stat.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for stdlib.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for string.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for memory.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for strings.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for inttypes.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for stdint.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3682: checking for unistd.h +configure:3698: gcc -c -g -O2 conftest.c >&5 +configure:3704: $? = 0 +configure:3708: test -z + || test ! -s conftest.err +configure:3711: $? = 0 +configure:3714: test -s conftest.o +configure:3717: $? = 0 +configure:3728: result: yes +configure:3754: checking dlfcn.h usability +configure:3766: gcc -c -g -O2 conftest.c >&5 +configure:3772: $? = 0 +configure:3776: test -z + || test ! -s conftest.err +configure:3779: $? = 0 +configure:3782: test -s conftest.o +configure:3785: $? = 0 +configure:3795: result: yes +configure:3799: checking dlfcn.h presence +configure:3809: gcc -E conftest.c +configure:3815: $? = 0 +configure:3835: result: yes +configure:3870: checking for dlfcn.h +configure:3877: result: yes +configure:3942: checking for g++ +configure:3971: result: no +configure:3942: checking for c++ +configure:3971: result: no +configure:3942: checking for gpp +configure:3958: found /dev/e/djgpp/bin/gpp +configure:3968: result: gpp +configure:3984: checking for C++ compiler version +configure:3987: gpp --version &5 +gpp.exe (GCC) 4.5.3 +Copyright (C) 2010 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. + +configure:3990: $? = 0 +configure:3992: gpp -v &5 +Using built-in specs. +COLLECT_GCC=e:/djgpp/bin/gpp.exe +COLLECT_LTO_WRAPPER=e:/djgpp/bin/../libexec/gcc/djgpp/4.53/lto-wrapper.exe +Target: djgpp +Configured with: /v204/gcc-4.53/configure djgpp --prefix=/dev/env/DJDIR --disable-nls --disable-werror --enable-languages=c,c++,fortran,objc,obj-c++,ada +Thread model: single +gcc version 4.5.3 (GCC) +configure:3995: $? = 0 +configure:3997: gpp -V &5 +gpp.exe: '-V' option must have argument +configure:4000: $? = 1 +configure:4003: checking whether we are using the GNU C++ compiler +configure:4027: gpp -c conftest.cc >&5 +configure:4033: $? = 0 +configure:4037: test -z + || test ! -s conftest.err +configure:4040: $? = 0 +configure:4043: test -s conftest.o +configure:4046: $? = 0 +configure:4059: result: yes +configure:4065: checking whether gpp accepts -g +configure:4086: gpp -c -g conftest.cc >&5 +configure:4092: $? = 0 +configure:4096: test -z + || test ! -s conftest.err +configure:4099: $? = 0 +configure:4102: test -s conftest.o +configure:4105: $? = 0 +configure:4116: result: yes +configure:4158: gpp -c -g -O2 conftest.cc >&5 +configure:4164: $? = 0 +configure:4168: test -z + || test ! -s conftest.err +configure:4171: $? = 0 +configure:4174: test -s conftest.o +configure:4177: $? = 0 +configure:4203: gpp -c -g -O2 conftest.cc >&5 +conftest.cc: In function 'int main()': +conftest.cc:24:9: error: 'exit' was not declared in this scope +configure:4209: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| /* end confdefs.h. */ +| +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:4158: gpp -c -g -O2 conftest.cc >&5 +conftest.cc:20:40: error: 'void std::exit(int)' should have been declared inside 'std' +In file included from conftest.cc:21:0: +e:/djgpp/include/stdlib.h:62:48: error: declaration of 'void std::exit(int)' throws different exceptions +conftest.cc:20:17: error: from previous declaration 'void std::exit(int) throw ()' +configure:4164: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| /* end confdefs.h. */ +| extern "C" void std::exit (int) throw (); using std::exit; +| #include +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:4158: gpp -c -g -O2 conftest.cc >&5 +conftest.cc:20:31: error: 'void std::exit(int)' should have been declared inside 'std' +configure:4164: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| /* end confdefs.h. */ +| extern "C" void std::exit (int); using std::exit; +| #include +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:4158: gpp -c -g -O2 conftest.cc >&5 +In file included from conftest.cc:21:0: +e:/djgpp/include/stdlib.h:62:48: error: declaration of 'void exit(int)' throws different exceptions +conftest.cc:20:17: error: from previous declaration 'void exit(int) throw ()' +configure:4164: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| /* end confdefs.h. */ +| extern "C" void exit (int) throw (); +| #include +| int +| main () +| { +| exit (42); +| ; +| return 0; +| } +configure:4158: gpp -c -g -O2 conftest.cc >&5 +configure:4164: $? = 0 +configure:4168: test -z + || test ! -s conftest.err +configure:4171: $? = 0 +configure:4174: test -s conftest.o +configure:4177: $? = 0 +configure:4203: gpp -c -g -O2 conftest.cc >&5 +configure:4209: $? = 0 +configure:4213: test -z + || test ! -s conftest.err +configure:4216: $? = 0 +configure:4219: test -s conftest.o +configure:4222: $? = 0 +configure:4255: checking how to run the C++ preprocessor +configure:4286: gpp -E conftest.cc +configure:4292: $? = 0 +configure:4324: gpp -E conftest.cc +conftest.cc:23:28: fatal error: ac_nonexistent.h: No such file or directory (ENOENT) +compilation terminated. +configure:4330: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| #include +configure:4369: result: gpp -E +configure:4393: gpp -E conftest.cc +configure:4399: $? = 0 +configure:4431: gpp -E conftest.cc +conftest.cc:23:28: fatal error: ac_nonexistent.h: No such file or directory (ENOENT) +compilation terminated. +configure:4437: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| #include +configure:4534: checking for g77 +configure:4563: result: no +configure:4534: checking for f77 +configure:4563: result: no +configure:4534: checking for xlf +configure:4563: result: no +configure:4534: checking for frt +configure:4563: result: no +configure:4534: checking for pgf77 +configure:4563: result: no +configure:4534: checking for fort77 +configure:4563: result: no +configure:4534: checking for fl32 +configure:4563: result: no +configure:4534: checking for af77 +configure:4563: result: no +configure:4534: checking for f90 +configure:4563: result: no +configure:4534: checking for xlf90 +configure:4563: result: no +configure:4534: checking for pgf90 +configure:4563: result: no +configure:4534: checking for epcf90 +configure:4563: result: no +configure:4534: checking for f95 +configure:4563: result: no +configure:4534: checking for fort +configure:4563: result: no +configure:4534: checking for xlf95 +configure:4563: result: no +configure:4534: checking for ifc +configure:4563: result: no +configure:4534: checking for efc +configure:4563: result: no +configure:4534: checking for pgf95 +configure:4563: result: no +configure:4534: checking for lf95 +configure:4563: result: no +configure:4534: checking for gfortran +configure:4563: result: no +configure:4578: checking for Fortran 77 compiler version +configure:4578: --version &5 +configure: --version: command not found +configure:4581: $? = 127 +configure:4583: -v &5 +configure: -v: command not found +configure:4586: $? = 127 +configure:4588: -V &5 +configure: -V: command not found +configure:4591: $? = 127 +configure:4599: checking whether we are using the GNU Fortran 77 compiler +configure:4613: -c conftest.F >&5 +configure: -c: command not found +configure:4619: $? = 127 +configure: failed program was: +| program main +| #ifndef __GNUC__ +| choke me +| #endif +| +| end +configure:4645: result: no +configure:4651: checking whether accepts -g +configure:4663: -c -g conftest.f >&5 +configure: -c: command not found +configure:4669: $? = 127 +configure: failed program was: +| program main +| +| end +configure:4694: result: no +configure:4724: checking the maximum length of command line arguments +configure:4833: result: 12288 +configure:4844: checking command to parse /dev/e/djgpp/bin/nm -B output from gcc object +configure:4949: gcc -c -g -O2 conftest.c >&5 +configure:4952: $? = 0 +configure:4956: /dev/e/djgpp/bin/nm -B conftest.o \| sed -n -e 's/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p' \> conftest.nm +configure:4959: $? = 0 +cannot find nm_test_var in conftest.nm +configure:4949: gcc -c -g -O2 conftest.c >&5 +configure:4952: $? = 0 +configure:4956: /dev/e/djgpp/bin/nm -B conftest.o \| sed -n -e 's/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*_\([_A-Za-z][_A-Za-z0-9]*\)$/\1 _\2 \2/p' \> conftest.nm +configure:4959: $? = 0 +configure:5011: gcc -o conftest.exe -g -O2 conftest.c conftstm.o >&5 +configure:5014: $? = 0 +configure:5052: result: ok +configure:5056: checking for objdir +configure:5071: result: .libs +configure:5161: checking for ar +configure:5177: found /dev/e/djgpp/bin/ar +configure:5188: result: ar +configure:5241: checking for ranlib +configure:5257: found /dev/e/djgpp/bin/ranlib +configure:5268: result: ranlib +configure:5321: checking for strip +configure:5337: found /dev/e/djgpp/bin/strip +configure:5348: result: strip +configure:5571: checking for correct ltmain.sh version +configure:5621: result: yes +configure:5681: checking if gcc supports -fno-rtti -fno-exceptions +configure:5702: gcc -c -g -O2 -fno-rtti -fno-exceptions conftest.c >&5 +cc1.exe: warning: command line option "-fno-rtti" is valid for C++/ObjC++ but not for C +configure:5706: $? = 0 +configure:5716: result: no +configure:5731: checking for gcc option to produce PIC +configure:5941: result: +configure:6012: checking if gcc static flag -static works +configure:6040: result: yes +configure:6050: checking if gcc supports -c -o file.o +configure:6074: gcc -c -g -O2 -o out/conftest2.o conftest.c >&5 +configure:6078: $? = 0 +configure:6097: result: yes +configure:6123: checking whether the gcc linker (e:/djgpp/bin/ld.exe) supports shared libraries +configure:7081: result: no +configure:7148: checking dynamic linker characteristics +configure:7773: result: no +configure:7782: checking how to hardcode library paths into programs +configure:7807: result: unsupported +configure:7821: checking whether stripping libraries is possible +configure:7826: result: yes +configure:8660: checking if libtool supports shared libraries +configure:8662: result: no +configure:8665: checking whether to build shared libraries +configure:8686: result: no +configure:8689: checking whether to build static libraries +configure:8693: result: yes +configure:8785: creating libtool +configure:9373: checking for ld used by gpp +configure:9440: result: e:/djgpp/bin/ld.exe +configure:9449: checking if the linker (e:/djgpp/bin/ld.exe) is GNU ld +configure:9464: result: yes +configure:9515: checking whether the gpp linker (e:/djgpp/bin/ld.exe) supports shared libraries +configure:10453: result: no +configure:10471: gpp -c -g -O2 conftest.cpp >&5 +configure:10474: $? = 0 +configure:10593: checking for gpp option to produce PIC +configure:10867: result: +configure:10938: checking if gpp static flag -static works +configure:10966: result: yes +configure:10976: checking if gpp supports -c -o file.o +configure:11000: gpp -c -g -O2 -o out/conftest2.o conftest.cpp >&5 +configure:11004: $? = 0 +configure:11023: result: yes +configure:11049: checking whether the gpp linker (e:/djgpp/bin/ld.exe) supports shared libraries +configure:11074: result: no +configure:11141: checking dynamic linker characteristics +configure:11766: result: no +configure:11775: checking how to hardcode library paths into programs +configure:11800: result: immediate +configure:18037: checking for a BSD-compatible install +configure:18092: result: /dev/env/DJDIR/bin/ginstall -c +configure:18107: checking for gawk +configure:18123: found /dev/e/djgpp/bin/gawk +configure:18133: result: gawk +configure:18270: checking whether to support threadsafe operation +configure:18274: result: no +configure:18378: checking whether to allow connections to be shared across threads +configure:18382: result: no +configure:18404: checking whether threads can override each others locks +configure:18408: result: no +configure:18427: checking whether to support shared library linked as release mode or not +configure:18431: result: no +configure:18450: checking whether to use an in-ram database for temporary tables +configure:18460: result: no +configure:18487: checking if executables have the .exe suffix +configure:18494: result: unknown +configure:18742: checking for library containing tgetent +configure:18772: gcc -o conftest.exe -g -O2 conftest.c >&5 +e:\djgpp\tmp/cc4Vnn5f.o: In function `main': +e:/myprogs/sqlite-3.5.6/conftest.c:34: undefined reference to `_tgetent' +collect2: ld returned 1 exit status +configure:18778: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char tgetent (); +| int +| main () +| { +| tgetent (); +| ; +| return 0; +| } +configure:18827: gcc -o conftest.exe -g -O2 conftest.c -lreadline >&5 +e:/djgpp/bin/ld.exe: cannot find -lreadline +collect2: ld returned 1 exit status +configure:18833: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char tgetent (); +| int +| main () +| { +| tgetent (); +| ; +| return 0; +| } +configure:18827: gcc -o conftest.exe -g -O2 conftest.c -lncurses >&5 +e:/djgpp/bin/ld.exe: cannot find -lncurses +collect2: ld returned 1 exit status +configure:18833: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char tgetent (); +| int +| main () +| { +| tgetent (); +| ; +| return 0; +| } +configure:18827: gcc -o conftest.exe -g -O2 conftest.c -lcurses >&5 +e:/djgpp/bin/ld.exe: cannot find -lcurses +collect2: ld returned 1 exit status +configure:18833: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char tgetent (); +| int +| main () +| { +| tgetent (); +| ; +| return 0; +| } +configure:18827: gcc -o conftest.exe -g -O2 conftest.c -ltermcap >&5 +e:/djgpp/bin/ld.exe: cannot find -ltermcap +collect2: ld returned 1 exit status +configure:18833: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char tgetent (); +| int +| main () +| { +| tgetent (); +| ; +| return 0; +| } +configure:18861: result: no +configure:18870: checking for readline in -lreadline +configure:18900: gcc -o conftest.exe -g -O2 conftest.c -lreadline >&5 +e:/djgpp/bin/ld.exe: cannot find -lreadline +collect2: ld returned 1 exit status +configure:18906: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char readline (); +| int +| main () +| { +| readline (); +| ; +| return 0; +| } +configure:18932: result: no +configure:18965: checking readline.h usability +configure:18977: gcc -c -g -O2 conftest.c >&5 +conftest.c:57:22: fatal error: readline.h: No such file or directory (ENOENT) +compilation terminated. +configure:18983: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| #include +| #if HAVE_SYS_TYPES_H +| # include +| #endif +| #if HAVE_SYS_STAT_H +| # include +| #endif +| #if STDC_HEADERS +| # include +| # include +| #else +| # if HAVE_STDLIB_H +| # include +| # endif +| #endif +| #if HAVE_STRING_H +| # if !STDC_HEADERS && HAVE_MEMORY_H +| # include +| # endif +| # include +| #endif +| #if HAVE_STRINGS_H +| # include +| #endif +| #if HAVE_INTTYPES_H +| # include +| #else +| # if HAVE_STDINT_H +| # include +| # endif +| #endif +| #if HAVE_UNISTD_H +| # include +| #endif +| #include +configure:19006: result: no +configure:19010: checking readline.h presence +configure:19020: gcc -E conftest.c +conftest.c:23:22: fatal error: readline.h: No such file or directory (ENOENT) +compilation terminated. +configure:19026: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| #include +configure:19046: result: no +configure:19081: checking for readline.h +configure:19088: result: no +configure:19101: checking for /usr/include/readline.h +configure:19116: result: no +configure:19101: checking for /usr/include/readline/readline.h +configure:19116: result: no +configure:19101: checking for /usr/local/include/readline.h +configure:19116: result: no +configure:19101: checking for /usr/local/include/readline/readline.h +configure:19116: result: no +configure:19101: checking for /usr/local/readline/include/readline.h +configure:19116: result: no +configure:19101: checking for /usr/local/readline/include/readline/readline.h +configure:19116: result: no +configure:19101: checking for /usr/contrib/include/readline.h +configure:19116: result: no +configure:19101: checking for /usr/contrib/include/readline/readline.h +configure:19116: result: no +configure:19101: checking for /mingw/include/readline.h +configure:19116: result: no +configure:19101: checking for /mingw/include/readline/readline.h +configure:19116: result: no +configure:19155: checking for library containing fdatasync +configure:19185: gcc -o conftest.exe -g -O2 conftest.c >&5 +e:\djgpp\tmp/ccyMkDkD.o: In function `main': +e:/myprogs/sqlite-3.5.6/conftest.c:34: undefined reference to `_fdatasync' +collect2: ld returned 1 exit status +configure:19191: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char fdatasync (); +| int +| main () +| { +| fdatasync (); +| ; +| return 0; +| } +configure:19240: gcc -o conftest.exe -g -O2 conftest.c -lrt >&5 +e:/djgpp/bin/ld.exe: cannot find -lrt +collect2: ld returned 1 exit status +configure:19246: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char fdatasync (); +| int +| main () +| { +| fdatasync (); +| ; +| return 0; +| } +configure:19274: result: no +configure:19301: checking for usleep +configure:19358: gcc -o conftest.exe -g -O2 conftest.c >&5 +configure:19364: $? = 0 +configure:19368: test -z + || test ! -s conftest.err +configure:19371: $? = 0 +configure:19374: test -s conftest.exe +configure:19377: $? = 0 +configure:19389: result: yes +configure:19400: checking for fdatasync +configure:19457: gcc -o conftest.exe -g -O2 conftest.c >&5 +e:\djgpp\tmp/cc7M3rBg.o: In function `main': +e:/myprogs/sqlite-3.5.6/conftest.c:63: undefined reference to `_fdatasync' +e:\djgpp\tmp/cc7M3rBg.o:conftest.c:(.data+0x0): undefined reference to `_fdatasync' +collect2: ld returned 1 exit status +configure:19463: $? = 1 +configure: failed program was: +| /* confdefs.h. */ +| +| #define PACKAGE_NAME "" +| #define PACKAGE_TARNAME "" +| #define PACKAGE_VERSION "" +| #define PACKAGE_STRING "" +| #define PACKAGE_BUGREPORT "" +| #define STDC_HEADERS 1 +| #define HAVE_SYS_TYPES_H 1 +| #define HAVE_SYS_STAT_H 1 +| #define HAVE_STDLIB_H 1 +| #define HAVE_STRING_H 1 +| #define HAVE_MEMORY_H 1 +| #define HAVE_STRINGS_H 1 +| #define HAVE_INTTYPES_H 1 +| #define HAVE_STDINT_H 1 +| #define HAVE_UNISTD_H 1 +| #define HAVE_DLFCN_H 1 +| #ifdef __cplusplus +| extern "C" void exit (int); +| #endif +| /* end confdefs.h. */ +| /* Define fdatasync to an innocuous variant, in case declares fdatasync. +| For example, HP-UX 11i declares gettimeofday. */ +| #define fdatasync innocuous_fdatasync +| +| /* System header to define __stub macros and hopefully few prototypes, +| which can conflict with char fdatasync (); below. +| Prefer to if __STDC__ is defined, since +| exists even on freestanding compilers. */ +| +| #ifdef __STDC__ +| # include +| #else +| # include +| #endif +| +| #undef fdatasync +| +| /* Override any gcc2 internal prototype to avoid an error. */ +| #ifdef __cplusplus +| extern "C" +| { +| #endif +| /* We use char because int might match the return type of a gcc2 +| builtin and then its argument prototype would still apply. */ +| char fdatasync (); +| /* 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_fdatasync) || defined (__stub___fdatasync) +| choke me +| #else +| char (*f) () = fdatasync; +| #endif +| #ifdef __cplusplus +| } +| #endif +| +| int +| main () +| { +| return f != fdatasync; +| ; +| return 0; +| } +configure:19488: result: no +configure:19625: creating ./config.status + +## ---------------------- ## +## Running config.status. ## +## ---------------------- ## + +This file was extended by config.status, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = + CONFIG_HEADERS = + CONFIG_LINKS = + CONFIG_COMMANDS = + $ ./config.status + +on SCHREIBTISCH_GP + +config.status:700: creating Makefile +config.status:700: creating sqlite3.pc + +## ---------------- ## +## Cache variables. ## +## ---------------- ## + +ac_cv_build=i386-pc-msdosdjgpp +ac_cv_build_alias=i386-pc-msdosdjgpp +ac_cv_c_compiler_gnu=yes +ac_cv_cxx_compiler_gnu=yes +ac_cv_env_CC_set= +ac_cv_env_CC_value= +ac_cv_env_CFLAGS_set= +ac_cv_env_CFLAGS_value= +ac_cv_env_CPPFLAGS_set= +ac_cv_env_CPPFLAGS_value= +ac_cv_env_CPP_set= +ac_cv_env_CPP_value= +ac_cv_env_CXXCPP_set= +ac_cv_env_CXXCPP_value= +ac_cv_env_CXXFLAGS_set= +ac_cv_env_CXXFLAGS_value= +ac_cv_env_CXX_set= +ac_cv_env_CXX_value= +ac_cv_env_F77_set= +ac_cv_env_F77_value= +ac_cv_env_FFLAGS_set= +ac_cv_env_FFLAGS_value= +ac_cv_env_LDFLAGS_set= +ac_cv_env_LDFLAGS_value= +ac_cv_env_build_alias_set= +ac_cv_env_build_alias_value= +ac_cv_env_host_alias_set= +ac_cv_env_host_alias_value= +ac_cv_env_target_alias_set= +ac_cv_env_target_alias_value= +ac_cv_exeext=.exe +ac_cv_f77_compiler_gnu=no +ac_cv_file__mingw_include_readline_h=no +ac_cv_file__mingw_include_readline_readline_h=no +ac_cv_file__usr_contrib_include_readline_h=no +ac_cv_file__usr_contrib_include_readline_readline_h=no +ac_cv_file__usr_include_readline_h=no +ac_cv_file__usr_include_readline_readline_h=no +ac_cv_file__usr_local_include_readline_h=no +ac_cv_file__usr_local_include_readline_readline_h=no +ac_cv_file__usr_local_readline_include_readline_h=no +ac_cv_file__usr_local_readline_include_readline_readline_h=no +ac_cv_func_fdatasync=no +ac_cv_func_usleep=yes +ac_cv_header_dlfcn_h=yes +ac_cv_header_inttypes_h=yes +ac_cv_header_memory_h=yes +ac_cv_header_readline_h=no +ac_cv_header_stdc=yes +ac_cv_header_stdint_h=yes +ac_cv_header_stdlib_h=yes +ac_cv_header_string_h=yes +ac_cv_header_strings_h=yes +ac_cv_header_sys_stat_h=yes +ac_cv_header_sys_types_h=yes +ac_cv_header_unistd_h=yes +ac_cv_host=i386-pc-msdosdjgpp +ac_cv_host_alias=i386-pc-msdosdjgpp +ac_cv_lib_readline_readline=no +ac_cv_objext=o +ac_cv_prog_AWK=gawk +ac_cv_prog_CPP='gcc -E' +ac_cv_prog_CXXCPP='gpp -E' +ac_cv_prog_LN_S='cp -p' +ac_cv_prog_ac_ct_AR=ar +ac_cv_prog_ac_ct_CC=gcc +ac_cv_prog_ac_ct_CXX=gpp +ac_cv_prog_ac_ct_RANLIB=ranlib +ac_cv_prog_ac_ct_STRIP=strip +ac_cv_prog_cc_g=yes +ac_cv_prog_cc_stdc= +ac_cv_prog_cxx_g=yes +ac_cv_prog_egrep='grep -E' +ac_cv_prog_f77_g=no +ac_cv_search_fdatasync=no +ac_cv_search_tgetent=no +lt_cv_deplibs_check_method=unknown +lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_ld_reload_flag=-r +lt_cv_objdir=.libs +lt_cv_path_LD=e:/djgpp/bin/ld.exe +lt_cv_path_LDCXX=e:/djgpp/bin/ld.exe +lt_cv_path_NM='/dev/e/djgpp/bin/nm -B' +lt_cv_path_SED=/dev/e/djgpp/bin/sed +lt_cv_prog_compiler_c_o=yes +lt_cv_prog_compiler_c_o_CXX=yes +lt_cv_prog_compiler_rtti_exceptions=no +lt_cv_prog_gnu_ld=yes +lt_cv_prog_gnu_ldcxx=yes +lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*_\([_A-Za-z][_A-Za-z0-9]*\)$/\1 _\2 \2/p'\''' +lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\) $/ {\"\1\", (lt_ptr) 0},/p'\'' -e '\''s/^[BCDEGRST] \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr) \&\2},/p'\''' +lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^. .* \(.*\)$/extern int \1;/p'\''' +lt_cv_sys_max_cmd_len=12288 +lt_lt_cv_prog_compiler_c_o='"yes"' +lt_lt_cv_prog_compiler_c_o_CXX='"yes"' +lt_lt_cv_sys_global_symbol_pipe='"sed -n -e '\''s/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*_\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 _\\2 \\2/p'\''"' +lt_lt_cv_sys_global_symbol_to_c_name_address='"sed -n -e '\''s/^: \\([^ ]*\\) \$/ {\\\"\\1\\\", (lt_ptr) 0},/p'\'' -e '\''s/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/ {\"\\2\", (lt_ptr) \\&\\2},/p'\''"' +lt_lt_cv_sys_global_symbol_to_cdecl='"sed -n -e '\''s/^. .* \\(.*\\)\$/extern int \\1;/p'\''"' + +## ----------------- ## +## Output variables. ## +## ----------------- ## + +ALLOWRELEASE='' +AR='ar' +AWK='gawk' +BUILD_CC='gcc' +BUILD_CFLAGS='-g -O2' +BUILD_EXEEXT='.exe' +CC='gcc' +CFLAGS='-g -O2' +CPP='gcc -E' +CPPFLAGS='' +CXX='gpp' +CXXCPP='gpp -E' +CXXFLAGS='-g -O2' +DEFS='-DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 ' +ECHO='echo' +ECHO_C='' +ECHO_N='-n' +ECHO_T='' +EGREP='grep -E' +EXEEXT='.exe' +F77='' +FFLAGS='' +HAVE_TCL='' +INSTALL_DATA='${INSTALL} -m 644' +INSTALL_PROGRAM='${INSTALL}' +INSTALL_SCRIPT='${INSTALL}' +LDFLAGS='' +LIBOBJS='' +LIBS='' +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +LN_S='ln' +LTLIBOBJS='' +OBJEXT='o' +OS_OS2='0' +OS_UNIX='0' +OS_WIN='1' +PACKAGE_BUGREPORT='' +PACKAGE_NAME='' +PACKAGE_STRING='' +PACKAGE_TARNAME='' +PACKAGE_VERSION='' +PATH_SEPARATOR=':' +RANLIB='ranlib' +RELEASE='3.5.6' +SHELL='/dev/env/DJDIR/bin/sh.exe' +SQLITE_THREADSAFE='0' +STRIP='strip' +TARGET_DEBUG='-DNDEBUG' +TARGET_EXEEXT='.exe' +TARGET_HAVE_READLINE='0' +TARGET_READLINE_INC='' +TARGET_READLINE_LIBS='' +TARGET_THREAD_LIB='' +TCL_BIN_DIR='' +TCL_INCLUDE_SPEC='' +TCL_LIBS='' +TCL_LIB_FILE='' +TCL_LIB_FLAG='' +TCL_LIB_SPEC='' +TCL_SRC_DIR='' +TCL_STUB_LIB_FILE='' +TCL_STUB_LIB_FLAG='' +TCL_STUB_LIB_SPEC='' +TCL_VERSION='' +TEMP_STORE='1' +THREADSOVERRIDELOCKS='-1' +VERSION='3.5' +VERSION_NUMBER='3005006' +XTHREADCONNECT='' +ac_ct_AR='ar' +ac_ct_CC='gcc' +ac_ct_CXX='gpp' +ac_ct_F77='' +ac_ct_RANLIB='ranlib' +ac_ct_STRIP='strip' +bindir='${exec_prefix}/bin' +build='i386-pc-msdosdjgpp' +build_alias='' +build_cpu='i386' +build_os='msdosdjgpp' +build_vendor='pc' +datadir='${prefix}/share' +exec_prefix='${prefix}' +host='SCHREIBTISCH_GP' +host_alias='' +host_cpu='i386' +host_os='msdosdjgpp' +host_vendor='pc' +includedir='${prefix}/include' +infodir='${prefix}/info' +libdir='${exec_prefix}/lib' +libexecdir='${exec_prefix}/libexec' +localstatedir='${prefix}/var' +mandir='${prefix}/man' +oldincludedir='/usr/include' +prefix='/dev/env/DJDIR' +program_prefix='' +program_transform_name='s,x,x,' +sbindir='${exec_prefix}/sbin' +sharedstatedir='${prefix}/com' +sysconfdir='${prefix}/etc' +target_alias='' + +## ----------- ## +## confdefs.h. ## +## ----------- ## + +#define HAVE_DLFCN_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_UNISTD_H 1 +#define PACKAGE_BUGREPORT "" +#define PACKAGE_NAME "" +#define PACKAGE_STRING "" +#define PACKAGE_TARNAME "" +#define PACKAGE_VERSION "" +#define STDC_HEADERS 1 +#endif +#ifdef __cplusplus +extern "C" void exit (int); + +configure: exit 0 diff --git a/client/src/thirdparty/sqlite-3.4.2/config.status b/client/src/thirdparty/sqlite-3.4.2/config.status new file mode 100644 index 0000000..38e924d --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/config.status @@ -0,0 +1,774 @@ +#! /dev/env/DJDIR/bin/sh.exe +# Generated by configure. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=${CONFIG_SHELL-/dev/env/DJDIR/bin/sh.exe} +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + 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=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # 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 before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, 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 + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +config_files=" Makefile sqlite3.pc" + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet 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] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to ." +ac_cs_version="\ +config.status +configured by configure, generated by GNU Autoconf 2.59, + with options \"'--disable-tcl' '--disable-threadsafe'\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=. +INSTALL="/dev/env/DJDIR/bin/ginstall -c" +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +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=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +if $ac_cs_recheck; then + echo "running /dev/env/DJDIR/bin/sh.exe configure " '--disable-tcl' '--disable-threadsafe' $ac_configure_extra_args " --no-create --no-recursion" >&6 + exec /dev/env/DJDIR/bin/sh.exe configure '--disable-tcl' '--disable-threadsafe' $ac_configure_extra_args --no-create --no-recursion +fi + +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "sqlite3.pc" ) CONFIG_FILES="$CONFIG_FILES sqlite3.pc" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t$/@;t t/; /@;t t$/s/[\\&,]/\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t$/,;t t/' >$tmp/subs.sed <<\CEOF +s,@SHELL@,/dev/env/DJDIR/bin/sh.exe,;t t +s,@PATH_SEPARATOR@,:,;t t +s,@PACKAGE_NAME@,,;t t +s,@PACKAGE_TARNAME@,,;t t +s,@PACKAGE_VERSION@,,;t t +s,@PACKAGE_STRING@,,;t t +s,@PACKAGE_BUGREPORT@,,;t t +s,@exec_prefix@,${prefix},;t t +s,@prefix@,/dev/env/DJDIR,;t t +s,@program_transform_name@,s,x,x,,;t t +s,@bindir@,${exec_prefix}/bin,;t t +s,@sbindir@,${exec_prefix}/sbin,;t t +s,@libexecdir@,${exec_prefix}/libexec,;t t +s,@datadir@,${prefix}/share,;t t +s,@sysconfdir@,${prefix}/etc,;t t +s,@sharedstatedir@,${prefix}/com,;t t +s,@localstatedir@,${prefix}/var,;t t +s,@libdir@,${exec_prefix}/lib,;t t +s,@includedir@,${prefix}/include,;t t +s,@oldincludedir@,/usr/include,;t t +s,@infodir@,${prefix}/info,;t t +s,@mandir@,${prefix}/man,;t t +s,@build_alias@,,;t t +s,@host_alias@,,;t t +s,@target_alias@,,;t t +s,@DEFS@,-DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 ,;t t +s,@ECHO_C@,,;t t +s,@ECHO_N@,-n,;t t +s,@ECHO_T@,,;t t +s,@LIBS@,,;t t +s,@build@,i386-pc-msdosdjgpp,;t t +s,@build_cpu@,i386,;t t +s,@build_vendor@,pc,;t t +s,@build_os@,msdosdjgpp,;t t +s,@host@,SCHREIBTISCH_GP,;t t +s,@host_cpu@,i386,;t t +s,@host_vendor@,pc,;t t +s,@host_os@,msdosdjgpp,;t t +s,@CC@,gcc,;t t +s,@CFLAGS@,-g -O2,;t t +s,@LDFLAGS@,,;t t +s,@CPPFLAGS@,,;t t +s,@ac_ct_CC@,gcc,;t t +s,@EXEEXT@,.exe,;t t +s,@OBJEXT@,o,;t t +s,@EGREP@,grep -E,;t t +s,@LN_S@,ln,;t t +s,@ECHO@,echo,;t t +s,@AR@,ar,;t t +s,@ac_ct_AR@,ar,;t t +s,@RANLIB@,ranlib,;t t +s,@ac_ct_RANLIB@,ranlib,;t t +s,@STRIP@,strip,;t t +s,@ac_ct_STRIP@,strip,;t t +s,@CPP@,gcc -E,;t t +s,@CXX@,gpp,;t t +s,@CXXFLAGS@,-g -O2,;t t +s,@ac_ct_CXX@,gpp,;t t +s,@CXXCPP@,gpp -E,;t t +s,@F77@,,;t t +s,@FFLAGS@,,;t t +s,@ac_ct_F77@,,;t t +s,@LIBTOOL@,$(SHELL) $(top_builddir)/libtool,;t t +s,@INSTALL_PROGRAM@,${INSTALL},;t t +s,@INSTALL_SCRIPT@,${INSTALL},;t t +s,@INSTALL_DATA@,${INSTALL} -m 644,;t t +s,@AWK@,gawk,;t t +s,@program_prefix@,,;t t +s,@VERSION@,3.5,;t t +s,@RELEASE@,3.5.6,;t t +s,@VERSION_NUMBER@,3005006,;t t +s,@BUILD_CC@,gcc,;t t +s,@BUILD_CFLAGS@,-g -O2,;t t +s,@SQLITE_THREADSAFE@,0,;t t +s,@TARGET_THREAD_LIB@,,;t t +s,@XTHREADCONNECT@,,;t t +s,@THREADSOVERRIDELOCKS@,-1,;t t +s,@ALLOWRELEASE@,,;t t +s,@TEMP_STORE@,1,;t t +s,@BUILD_EXEEXT@,.exe,;t t +s,@OS_UNIX@,0,;t t +s,@OS_WIN@,1,;t t +s,@OS_OS2@,0,;t t +s,@TARGET_EXEEXT@,.exe,;t t +s,@TCL_VERSION@,,;t t +s,@TCL_BIN_DIR@,,;t t +s,@TCL_SRC_DIR@,,;t t +s,@TCL_LIBS@,,;t t +s,@TCL_INCLUDE_SPEC@,,;t t +s,@TCL_LIB_FILE@,,;t t +s,@TCL_LIB_FLAG@,,;t t +s,@TCL_LIB_SPEC@,,;t t +s,@TCL_STUB_LIB_FILE@,,;t t +s,@TCL_STUB_LIB_FLAG@,,;t t +s,@TCL_STUB_LIB_SPEC@,,;t t +s,@HAVE_TCL@,,;t t +s,@TARGET_READLINE_LIBS@,,;t t +s,@TARGET_READLINE_INC@,,;t t +s,@TARGET_HAVE_READLINE@,0,;t t +s,@TARGET_DEBUG@,-DNDEBUG,;t t +s,@LIBOBJS@,,;t t +s,@LTLIBOBJS@,,;t t +CEOF + + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + sed "/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +} + +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done + +{ (exit 0); exit 0; } diff --git a/client/src/thirdparty/sqlite-3.4.2/config.sub b/client/src/thirdparty/sqlite-3.4.2/config.sub new file mode 100644 index 0000000..2a4932e --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/config.sub @@ -0,0 +1,1640 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2007-01-18' + +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# 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 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. + +# 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 +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-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + 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) + os= + basic_machine=$1 + ;; + -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 \ + | 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 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx | dvp \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]a*eb | 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 | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-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-* \ + | 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-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | 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-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | 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-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]a*eb-* | 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-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # 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 + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + 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 + ;; + cr16c) + basic_machine=cr16c-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 + ;; + 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'm not sure what "Sysv32" means. Should this be sysv3.2? + 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 + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mipsEE* | ee | ps2) + basic_machine=mips64r5900el-scei + case $os in + -linux*) + ;; + *) + os=-elf + ;; + esac + ;; + iop) + basic_machine=mipsel-scei + os=-irx + ;; + dvp) + basic_machine=dvp-scei + os=-elf + ;; + 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-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + 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 + ;; + 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 + ;; + 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) basic_machine=powerpc-unknown + ;; + ppc-*) 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 + ;; + 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 + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + 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 + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-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[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. + -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* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -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* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -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* | -irx*) + # 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 + ;; + -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 + ;; + # 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 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + 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 + ;; + -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/client/src/thirdparty/sqlite-3.4.2/configure b/client/src/thirdparty/sqlite-3.4.2/configure new file mode 100644 index 0000000..b7ec403 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/configure @@ -0,0 +1,20477 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.59. +# +# Copyright (C) 2003 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. ## +## --------------------- ## + +# 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + 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=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # 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 before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, 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 + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { 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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${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 </dev/null 2>&1 && unset CDPATH + +if test -z "$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 && + echo_test_string=`eval $cmd` && + (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. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +tagnames=${tagnames+${tagnames},}CXX + +tagnames=${tagnames+${tagnames},}F77 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/sqlite.h.in" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# 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 datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP CPP CXX CXXFLAGS ac_ct_CXX CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AWK program_prefix VERSION RELEASE VERSION_NUMBER BUILD_CC BUILD_CFLAGS SQLITE_THREADSAFE TARGET_THREAD_LIB XTHREADCONNECT THREADSOVERRIDELOCKS ALLOWRELEASE TEMP_STORE BUILD_EXEEXT OS_UNIX OS_WIN OS_OS2 TARGET_EXEEXT TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_LIBS 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 LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + 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 && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + 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 +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP +ac_env_F77_set=${F77+set} +ac_env_F77_value=$F77 +ac_cv_env_F77_set=${F77+set} +ac_cv_env_F77_value=$F77 +ac_env_FFLAGS_set=${FFLAGS+set} +ac_env_FFLAGS_value=$FFLAGS +ac_cv_env_FFLAGS_set=${FFLAGS+set} +ac_cv_env_FFLAGS_value=$FFLAGS + +# +# Report the --help message. +# +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 this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --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 + --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 + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-shared[=PKGS] + build shared libraries [default=yes] + --enable-static[=PKGS] + build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-threadsafe Support threadsafe operation + --enable-cross-thread-connections + Allow connection sharing across threads + --enable-threads-override-locks + Threads can override each others locks + --enable-releasemode Support libtool link to release mode + --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-debug enable debugging & verbose explain + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-tags[=TAGS] + include additional configurations [automatic] + --with-hints=FILE Read configuration options from FILE + --with-tcl=DIR directory containing tcl configuration + (tclConfig.sh) + --with-readline-lib specify readline library + --with-readline-inc specify readline include paths + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + F77 Fortran 77 compiler command + FFLAGS Fortran 77 compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright (C) 2003 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 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +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 || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + 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; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >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 + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + 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 + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +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 + + + + + + + + + + + + + + + + + + + + +# The following RCS revision string applies to configure.in +# $Revision: 1.45 $ + +######### +# Programs needed +# +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi; + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi; + +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + 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," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi; + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +ac_ext=c +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 +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +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_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" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out 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. +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +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 +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + 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 + { { 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 +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 +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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 +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f 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 +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_ext=c +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 + +echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 +if test "${lt_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done + +fi + +SED=$lt_cv_path_SED +echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6 + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi; +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 + case $host in + *-*-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` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + 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" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 +else + echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + 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" + # 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 +echo "${ECHO_T}$LD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 +with_gnu_ld=$lt_cv_prog_gnu_ld + + +echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + 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 + ;; +esac + +echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + 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 + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + 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 + # Check to see if the nm accepts a BSD-compat flag. + # 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 + 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 + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6 +NM="$lt_cv_path_NM" + +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + +echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 +echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +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. +# '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 +# 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 +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump'. + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | kfreebsd*-gnu | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + 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]) 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_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +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)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 +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 + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + +fi; +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 which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 3088 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +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 + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +lt_cv_cc_needs_belf=no +fi +rm -f 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' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$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 + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + + +esac + +need_locks="$enable_libtool_lock" + + +ac_ext=c +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 +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&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 + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # 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 +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent 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 +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + 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 + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # 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 +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent 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 +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + 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 + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +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 + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f 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 +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +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 +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +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 + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +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=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&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 { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&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 { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&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 { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + 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 +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + '' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +#include +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f 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 +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # 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 +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent 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 +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + 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 + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # 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 +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent 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 +/* end confdefs.h. */ +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + 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 + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi + + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran + 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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$F77"; then + ac_cv_prog_F77="$F77" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_F77="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +F77=$ac_cv_prog_F77 +if test -n "$F77"; then + echo "$as_me:$LINENO: result: $F77" >&5 +echo "${ECHO_T}$F77" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$F77" && break + done +fi +if test -z "$F77"; then + ac_ct_F77=$F77 + for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_F77"; then + ac_cv_prog_ac_ct_F77="$ac_ct_F77" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_F77="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_F77=$ac_cv_prog_ac_ct_F77 +if test -n "$ac_ct_F77"; then + echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 +echo "${ECHO_T}$ac_ct_F77" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_F77" && break +done + + F77=$ac_ct_F77 +fi + + +# Provide some information about the compiler. +echo "$as_me:4578:" \ + "checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +rm -f a.out + +# If we don't use `.F' as extension, the preprocessor is not run on the +# input file. (Note that this only needs to work for GNU compilers.) +ac_save_ext=$ac_ext +ac_ext=F +echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6 +if test "${ac_cv_f77_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF + program main +#ifndef __GNUC__ + choke me +#endif + + end +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_f77_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6 +ac_ext=$ac_save_ext +ac_test_FFLAGS=${FFLAGS+set} +ac_save_FFLAGS=$FFLAGS +FFLAGS= +echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 +echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_f77_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + FFLAGS=-g +cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_f77_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_f77_g=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 +echo "${ECHO_T}$ac_cv_prog_f77_g" >&6 +if test "$ac_test_FFLAGS" = set; then + FFLAGS=$ac_save_FFLAGS +elif test $ac_cv_prog_f77_g = yes; then + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-g -O2" + else + FFLAGS="-g" + fi +else + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-O2" + else + FFLAGS= + fi +fi + +G77=`test $ac_compiler_gnu = yes && echo yes` +ac_ext=c +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 + + + +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + +# find the maximum length of command line arguments +echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6 +if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + 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; + ;; + + 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` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + 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` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + 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 + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # 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. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 +echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6 +else + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 +fi + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6 +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; 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 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext 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:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +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 + echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6 +else + echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 +fi + +echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6 +if test "${lt_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +echo "${ECHO_T}$lt_cv_objdir" >&6 +objdir=$lt_cv_objdir + + + + + +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 "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. +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 to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false" +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + AR=$ac_ct_AR +else + AR="$ac_cv_prog_AR" +fi + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +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 +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + 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 + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + 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 -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" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6 +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + 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 + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + 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 -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" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +enable_dlopen=no +enable_win32_dll=no + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + +fi; +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + + +# Check whether --with-pic or --without-pic was given. +if test "${with_pic+set}" = set; then + withval="$with_pic" + pic_mode="$withval" +else + pic_mode=default +fi; +test -z "$pic_mode" && pic_mode=default + +# Check if we have a version mismatch between libtool.m4 and ltmain.sh. +# +# Note: This should be in AC_LIBTOOL_SETUP, _after_ $ltmain have been defined. +# We also should do it _before_ AC_LIBTOOL_LANG_C_CONFIG that actually +# calls AC_LIBTOOL_CONFIG and creates libtool. +# +echo "$as_me:$LINENO: checking for correct ltmain.sh version" >&5 +echo $ECHO_N "checking for correct ltmain.sh version... $ECHO_C" >&6 +if test "x$ltmain" = "x" ; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: + +*** [Gentoo] sanity check failed! *** +*** \$ltmain is not defined, please check the patch for consistency! *** +" >&5 +echo "$as_me: error: + +*** [Gentoo] sanity check failed! *** +*** \$ltmain is not defined, please check the patch for consistency! *** +" >&2;} + { (exit 1); exit 1; }; } +fi +gentoo_lt_version="1.5.22" +gentoo_ltmain_version=`sed -n '/^[ ]*VERSION=/{s/^[ ]*VERSION=//;p;q;}' "$ltmain"` +if test "x$gentoo_lt_version" != "x$gentoo_ltmain_version" ; then + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + { { echo "$as_me:$LINENO: error: + +*** [Gentoo] sanity check failed! *** +*** libtool.m4 and ltmain.sh have a version mismatch! *** +*** (libtool.m4 = $gentoo_lt_version, ltmain.sh = $gentoo_ltmain_version) *** + +Please run: + + libtoolize --copy --force + +if appropriate, please contact the maintainer of this +package (or your distribution) for help. +" >&5 +echo "$as_me: error: + +*** [Gentoo] sanity check failed! *** +*** libtool.m4 and ltmain.sh have a version mismatch! *** +*** (libtool.m4 = $gentoo_lt_version, ltmain.sh = $gentoo_ltmain_version) *** + +Please run: + + libtoolize --copy --force + +if appropriate, please contact the maintainer of this +package (or your distribution) for help. +" >&2;} + { (exit 1); exit 1; }; } +else + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +# Use C for the default configuration in the libtool script +tagname= +lt_save_CC="$CC" +ac_ext=c +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 + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + +echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:5702: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:5706: \$? = $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 "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 + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 + +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 + : +fi + +fi + +lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + 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 "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # 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' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + 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 "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # 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' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + +echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:5970: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:5974: \$? = $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 "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_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6 + +if test x"$lt_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$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 "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_prog_compiler_static_works=yes + fi + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:6074: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:6078: \$? = $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 "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 + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +echo "${ECHO_T}$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 + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + runpath_var= + allow_undefined_flag= + enable_shared_with_static_runtimes=no + archive_cmds= + archive_expsym_cmds= + old_archive_From_new_cmds= + old_archive_from_expsyms_cmds= + export_dynamic_flag_spec= + whole_archive_flag_spec= + thread_safe_flag_spec= + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + link_all_deplibs=unknown + hardcode_automatic=no + module_cmds= + module_expsym_cmds= + always_export_symbols=no + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # 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'. + exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + # 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 + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + 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-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # 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 "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + 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' + # 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' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <&2 + +*** 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 modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + 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' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + 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/'\'' | $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 (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 + ;; + + interix3*) + hardcode_direct=no + hardcode_shlibpath_var=no + 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' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + 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; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + 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' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; 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 -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + 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 + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + 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 + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** 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 +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + 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 "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + 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 + fi + ;; + + aix4* | aix5*) + 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="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -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")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + 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 + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + + 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` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + 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 "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # 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_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. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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" + 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 "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + 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" + 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 +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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" + # 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' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # 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 + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + 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 "$deplibs" | $SED -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*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + if test "$GCC" = 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' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + 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 + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + 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 "$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 $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + 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' + ;; + + hpux10*) + 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 "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + hardcode_direct=yes + 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 + fi + ;; + + hpux11*) + 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' + ;; + ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -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' + ;; + 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}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + 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 + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld='-rpath $libdir' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + 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_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + hardcode_direct=yes + hardcode_shlibpath_var=no + 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' + else + 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 + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + 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 "$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 ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + 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 ${wl}-set_version ${wl}$verstring` ${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='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -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; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -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' + fi + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${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 ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + 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' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + 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' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + 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' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # 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' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6 +test "$ld_shlibs" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # 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. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 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:$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=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + 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* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 +echo "${ECHO_T}$archive_cmds_need_lc" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + 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 ';' >/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. + 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 +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + 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' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + 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}' + 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 + # 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 + : + else + can_build_shared=no + fi + ;; + esac + # 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. + 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}' + 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' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + 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=`$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' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + 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' + 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" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + 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'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + 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="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + 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}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; 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 -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + 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 + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${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`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + 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' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # 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} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + 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*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + 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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + 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 "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + 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' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + 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' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + 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' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + 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}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + 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}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + 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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # 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 + + # 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)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + 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' + 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' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + 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 + ;; + +nto-qnx*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # 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 + 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' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + 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}' + 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" + ;; + +solaris*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + 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 "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + 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) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + 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=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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + 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 + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var" || \ + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existant directories. + 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 "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6 + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&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" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + ;; + *) + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + ;; + esac +fi + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +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 +#else +char (*f) () = shl_load; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shl_load; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shl_load=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6 +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +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 +#else +char (*f) () = dlopen; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != dlopen; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6 +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_svld_dlopen=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dld_link (); +int +main () +{ +dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_dld_link=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + 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 "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + 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 < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$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\" + echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + 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 < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# Report which library types will actually be built +echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 +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 "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6 + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # 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 + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler \ + CC \ + LD \ + lt_prog_compiler_wl \ + lt_prog_compiler_pic \ + lt_prog_compiler_static \ + lt_prog_compiler_no_builtin_flag \ + export_dynamic_flag_spec \ + thread_safe_flag_spec \ + whole_archive_flag_spec \ + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ + module_cmds | \ + module_expsym_cmds | \ + old_archive_from_expsyms_cmds | \ + export_symbols_cmds | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + { echo "$as_me:$LINENO: creating $ofile" >&5 +echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" +#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 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 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# 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. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# 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 + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# 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. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +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 in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# 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 DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# 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 "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # 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) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +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 + +CC="$lt_save_CC" + + +# Check whether --with-tags or --without-tags was given. +if test "${with_tags+set}" = set; then + withval="$with_tags" + tagnames="$withval" +fi; + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} + else + { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 +echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in + "") ;; + *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 +echo "$as_me: error: invalid tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 +echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} + { (exit 1); exit 1; }; } + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +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-%%"` + + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' +else + lt_prog_compiler_no_builtin_flag_CXX= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi; +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 + case $host in + *-*-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` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + 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" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 +else + echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + 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" + # 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 +echo "${ECHO_T}$LD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 +ld_shlibs_CXX=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix4* | aix5*) + 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="" + else + 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 + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + + if test "$GXX" = 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` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_CXX=yes + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + 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 "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # 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_CXX=yes + 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_CXX='-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 +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$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. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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_CXX='${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_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_CXX="\$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 + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $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_CXX='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 -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_CXX='+b $libdir' + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + interix3*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${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_CXX='$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_CXX='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' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # 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. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +esac +echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6 +test "$ld_shlibs_CXX" = no && can_build_shared=no + +GCC_CXX="$GXX" +LD_CXX="$LD" + + +cat > conftest.$ac_ext <&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$rm -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + postdeps_CXX='-lCstd -lCrun' + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + +lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # 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_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_CXX='-qnocommon' + lt_prog_compiler_wl_CXX='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + +echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:10896: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:10900: \$? = $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 "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_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6 + +if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$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 "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_prog_compiler_static_works_CXX=yes + fi + else + lt_prog_compiler_static_works_CXX=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6 + +if test x"$lt_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:11000: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:11004: \$? = $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 "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_CXX=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -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_CXX='$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_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6 +test "$ld_shlibs_CXX" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # 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. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + 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 ';' >/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. + 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 +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + 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' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + 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}' + 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 + # 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 + : + else + can_build_shared=no + fi + ;; + esac + # 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. + 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}' + 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' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + 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=`$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' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + 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' + 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" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + 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'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + 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="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + 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}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; 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 -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + 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 + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${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`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + 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' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # 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} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + 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*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + 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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + 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 "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + 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' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + 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' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + 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' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + 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}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + 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}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + 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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # 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 + + # 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)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + 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' + 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' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + 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 + ;; + +nto-qnx*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # 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 + 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' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + 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}' + 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" + ;; + +solaris*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + 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 "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + 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) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + 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=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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + 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 + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || \ + test -n "$runpath_var_CXX" || \ + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_CXX" != 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 "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 +echo "${ECHO_T}$hardcode_action_CXX" >&6 + +if test "$hardcode_action_CXX" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # 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 + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_CXX \ + CC_CXX \ + LD_CXX \ + lt_prog_compiler_wl_CXX \ + lt_prog_compiler_pic_CXX \ + lt_prog_compiler_static_CXX \ + lt_prog_compiler_no_builtin_flag_CXX \ + export_dynamic_flag_spec_CXX \ + thread_safe_flag_spec_CXX \ + whole_archive_flag_spec_CXX \ + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ + module_cmds_CXX | \ + module_expsym_cmds_CXX | \ + old_archive_from_expsyms_cmds_CXX | \ + export_symbols_cmds_CXX | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_CXX + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_CXX +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_CXX + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# 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. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +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 in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# 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_CXX + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_CXX" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +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 + +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu + + +archive_cmds_need_lc_F77=no +allow_undefined_flag_F77= +always_export_symbols_F77=no +archive_expsym_cmds_F77= +export_dynamic_flag_spec_F77= +hardcode_direct_F77=no +hardcode_libdir_flag_spec_F77= +hardcode_libdir_flag_spec_ld_F77= +hardcode_libdir_separator_F77= +hardcode_minus_L_F77=no +hardcode_automatic_F77=no +module_cmds_F77= +module_expsym_cmds_F77= +link_all_deplibs_F77=unknown +old_archive_cmds_F77=$old_archive_cmds +no_undefined_flag_F77= +whole_archive_flag_spec_F77= +enable_shared_with_static_runtimes_F77=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +objext_F77=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +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-%%"` + + +echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 +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 "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6 + +GCC_F77="$G77" +LD_F77="$LD" + +lt_prog_compiler_wl_F77= +lt_prog_compiler_pic_F77= +lt_prog_compiler_static_F77= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + if test "$GCC" = yes; then + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_static_F77='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # 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_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_F77=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_F77='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + else + lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # 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_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_F77='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_F77='-Qoption ld ' + lt_prog_compiler_pic_F77='-PIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_F77='-Kconform_pic' + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_can_build_shared_F77=no + ;; + + uts4*) + lt_prog_compiler_pic_F77='-pic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_F77=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_F77"; then + +echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:12607: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:12611: \$? = $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 "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_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6 + +if test x"$lt_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac +else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_F77= + ;; + *) + lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$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 "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_prog_compiler_static_works_F77=yes + fi + else + lt_prog_compiler_static_works_F77=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6 + +if test x"$lt_prog_compiler_static_works_F77" = xyes; then + : +else + lt_prog_compiler_static_F77= +fi + + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:12711: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:12715: \$? = $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 "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_F77=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + runpath_var= + allow_undefined_flag_F77= + enable_shared_with_static_runtimes_F77=no + archive_cmds_F77= + archive_expsym_cmds_F77= + old_archive_From_new_cmds_F77= + old_archive_from_expsyms_cmds_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + thread_safe_flag_spec_F77= + hardcode_libdir_flag_spec_F77= + hardcode_libdir_flag_spec_ld_F77= + hardcode_libdir_separator_F77= + hardcode_direct_F77=no + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=unsupported + link_all_deplibs_F77=unknown + hardcode_automatic_F77=no + module_cmds_F77= + module_expsym_cmds_F77= + always_export_symbols_F77=no + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # 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'. + exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + # 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 + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + 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-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # 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 "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_F77=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + 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_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${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_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <&2 + +*** 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 modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_F77=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_F77=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes + export_symbols_cmds_F77='$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_F77='$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_F77='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_F77=no + fi + ;; + + interix3*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${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_F77='$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_F77='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' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${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*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_F77='${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' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_F77=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_F77=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_F77=no + cat <<_LT_EOF 1>&2 + +*** 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 +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + + if test "$ld_shlibs_F77" = no; then + runpath_var= + hardcode_libdir_flag_spec_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=yes + archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_F77=yes + 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_F77=unsupported + fi + ;; + + aix4* | aix5*) + 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="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -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_F77='$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_F77='$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 + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_F77='' + hardcode_direct_F77=yes + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + + 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` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_F77=yes + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_libdir_separator_F77= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + 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 "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # 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_F77=yes + 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_F77='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_F77="-z nodefs" + archive_expsym_cmds_F77="\$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. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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_F77='${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_F77=' ${wl}-bernotok' + allow_undefined_flag_F77=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_F77='$convenience' + archive_cmds_need_lc_F77=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_F77="\$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 + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_F77=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_F77=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_F77=' ' + allow_undefined_flag_F77=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_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_F77=no + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='' + link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + freebsd1*) + ld_shlibs_F77=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 + # extra space). + freebsd2.2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_F77='$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_F77='$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_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$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_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + ;; + *) + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + link_all_deplibs_F77=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + newsos6) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$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_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_F77='-rpath $libdir' + fi + hardcode_libdir_separator_F77=: + ;; + + solaris*) + no_undefined_flag_F77=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$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' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + 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_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_F77='$CC -r -o $output$reload_objs' + hardcode_direct_F77=no + ;; + motorola) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv4.3*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # 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_F77='${wl}-z,text' + allow_undefined_flag_F77='${wl}-z,nodefs' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + export_dynamic_flag_spec_F77='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + *) + ld_shlibs_F77=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 +echo "${ECHO_T}$ld_shlibs_F77" >&6 +test "$ld_shlibs_F77" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_F77" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_F77=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_F77 in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # 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. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_F77 + pic_flag=$lt_prog_compiler_pic_F77 + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_F77 + allow_undefined_flag_F77= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_F77=no + else + archive_cmds_need_lc_F77=yes + fi + allow_undefined_flag_F77=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + 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 ';' >/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. + 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 +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + 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' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + 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}' + 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 + # 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 + : + else + can_build_shared=no + fi + ;; + esac + # 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. + 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}' + 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' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + 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=`$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' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + 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' + 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" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + 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'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + 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="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + 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}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; 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 -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + 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 + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${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`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + 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' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # 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} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + 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*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + 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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + 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 "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + 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' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + 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' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + 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' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + 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}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + 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}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + 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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # 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 + + # 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)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + 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' + 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' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + 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 + ;; + +nto-qnx*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # 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 + 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' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + 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}' + 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" + ;; + +solaris*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + 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 "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + 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) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + 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=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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + 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 + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action_F77= +if test -n "$hardcode_libdir_flag_spec_F77" || \ + test -n "$runpath_var_F77" || \ + test "X$hardcode_automatic_F77" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_F77" != 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 "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && + test "$hardcode_minus_L_F77" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_F77=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_F77=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_F77=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 +echo "${ECHO_T}$hardcode_action_F77" >&6 + +if test "$hardcode_action_F77" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # 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 + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_F77 \ + CC_F77 \ + LD_F77 \ + lt_prog_compiler_wl_F77 \ + lt_prog_compiler_pic_F77 \ + lt_prog_compiler_static_F77 \ + lt_prog_compiler_no_builtin_flag_F77 \ + export_dynamic_flag_spec_F77 \ + thread_safe_flag_spec_F77 \ + whole_archive_flag_spec_F77 \ + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ + module_cmds_F77 | \ + module_expsym_cmds_F77 | \ + old_archive_from_expsyms_cmds_F77 | \ + export_symbols_cmds_F77 | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_F77 + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_F77 + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_F77 + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_F77 + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_F77 + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_F77 +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_F77 + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_F77 +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_F77 +archive_expsym_cmds=$lt_archive_expsym_cmds_F77 +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_F77 +module_expsym_cmds=$lt_module_expsym_cmds_F77 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_F77 + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_F77 + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + +# 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. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_F77 + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_F77 + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +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 in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_F77 + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 + +# 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_F77 + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_F77 + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_F77 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_F77 + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_F77 + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_F77" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_F77 + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_F77 + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_F77 + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_F77 + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +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 + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + + + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +objext_GCJ=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC +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-%%"` + + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + +old_archive_cmds_GCJ=$old_archive_cmds + + +lt_prog_compiler_no_builtin_flag_GCJ= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' + + +echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:14951: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:14955: \$? = $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 "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 + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl_GCJ= +lt_prog_compiler_pic_GCJ= +lt_prog_compiler_static_GCJ= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + if test "$GCC" = yes; then + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_static_GCJ='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # 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_GCJ='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_GCJ=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_GCJ='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + else + lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # 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_GCJ='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_GCJ='-Qoption ld ' + lt_prog_compiler_pic_GCJ='-PIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_GCJ='-Kconform_pic' + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_can_build_shared_GCJ=no + ;; + + uts4*) + lt_prog_compiler_pic_GCJ='-pic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_GCJ=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_GCJ"; then + +echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -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:15219: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:15223: \$? = $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 "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_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6 + +if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac +else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_GCJ= + ;; + *) + lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$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 "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_prog_compiler_static_works_GCJ=yes + fi + else + lt_prog_compiler_static_works_GCJ=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6 + +if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then + : +else + lt_prog_compiler_static_GCJ= +fi + + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # 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 + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -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:15323: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:15327: \$? = $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 "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_GCJ=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + runpath_var= + allow_undefined_flag_GCJ= + enable_shared_with_static_runtimes_GCJ=no + archive_cmds_GCJ= + archive_expsym_cmds_GCJ= + old_archive_From_new_cmds_GCJ= + old_archive_from_expsyms_cmds_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + thread_safe_flag_spec_GCJ= + hardcode_libdir_flag_spec_GCJ= + hardcode_libdir_flag_spec_ld_GCJ= + hardcode_libdir_separator_GCJ= + hardcode_direct_GCJ=no + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=unsupported + link_all_deplibs_GCJ=unknown + hardcode_automatic_GCJ=no + module_cmds_GCJ= + module_expsym_cmds_GCJ= + always_export_symbols_GCJ=no + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # 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'. + exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + # 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 + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + 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-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # 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 "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_GCJ=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + 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_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${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_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <&2 + +*** 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 modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_GCJ=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_GCJ=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes + export_symbols_cmds_GCJ='$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_GCJ='$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_GCJ='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_GCJ=no + fi + ;; + + interix3*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${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_GCJ='$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_GCJ='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' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${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*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_GCJ='${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' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_GCJ=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_GCJ=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_GCJ=no + cat <<_LT_EOF 1>&2 + +*** 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 +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + + if test "$ld_shlibs_GCJ" = no; then + runpath_var= + hardcode_libdir_flag_spec_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=yes + archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_GCJ=yes + 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_GCJ=unsupported + fi + ;; + + aix4* | aix5*) + 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="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -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_GCJ='$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_GCJ='$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 + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_GCJ='' + hardcode_direct_GCJ=yes + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + + 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` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_GCJ=yes + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_libdir_separator_GCJ= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + 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 "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # 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_GCJ=yes + 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_GCJ='-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 +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_GCJ="-z nodefs" + archive_expsym_cmds_GCJ="\$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. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# 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 '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f 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_GCJ='${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_GCJ=' ${wl}-bernotok' + allow_undefined_flag_GCJ=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_GCJ='$convenience' + archive_cmds_need_lc_GCJ=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_GCJ="\$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 + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_GCJ=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_GCJ=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_GCJ=' ' + allow_undefined_flag_GCJ=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_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_GCJ=no + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='' + link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + freebsd1*) + ld_shlibs_GCJ=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 + # extra space). + freebsd2.2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$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_GCJ='$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_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$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_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + ;; + *) + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + link_all_deplibs_GCJ=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + newsos6) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$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_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_GCJ='-rpath $libdir' + fi + hardcode_libdir_separator_GCJ=: + ;; + + solaris*) + no_undefined_flag_GCJ=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$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' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + 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_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_GCJ='$CC -r -o $output$reload_objs' + hardcode_direct_GCJ=no + ;; + motorola) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4.3*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # 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_GCJ='${wl}-z,text' + allow_undefined_flag_GCJ='${wl}-z,nodefs' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + *) + ld_shlibs_GCJ=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 +echo "${ECHO_T}$ld_shlibs_GCJ" >&6 +test "$ld_shlibs_GCJ" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_GCJ" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_GCJ=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_GCJ in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # 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. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_GCJ + pic_flag=$lt_prog_compiler_pic_GCJ + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ + allow_undefined_flag_GCJ= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_GCJ=no + else + archive_cmds_need_lc_GCJ=yes + fi + allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + 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 ';' >/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. + 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 +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + 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' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + 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}' + 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 + # 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 + : + else + can_build_shared=no + fi + ;; + esac + # 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. + 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}' + 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' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + 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=`$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' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + 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' + 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" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + 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'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + 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="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + 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}' + ;; + esac + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + supports_anon_versioning=no + case `$LD -v 2>/dev/null` 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 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; 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 -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + $archive_expsym_cmds="$archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + 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 + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${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`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + 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' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + # 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} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + 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*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + 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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + 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 "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + 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' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + 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' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + 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' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + 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}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + 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}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + 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' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # 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 + + # 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)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + 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' + 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' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + 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 + ;; + +nto-qnx*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # 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 + 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' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + 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}' + 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" + ;; + +solaris*) + 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' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + 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 "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + 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) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + 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=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' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + 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 + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action_GCJ= +if test -n "$hardcode_libdir_flag_spec_GCJ" || \ + test -n "$runpath_var_GCJ" || \ + test "X$hardcode_automatic_GCJ" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_GCJ" != 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 "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && + test "$hardcode_minus_L_GCJ" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_GCJ=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_GCJ=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_GCJ=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 +echo "${ECHO_T}$hardcode_action_GCJ" >&6 + +if test "$hardcode_action_GCJ" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # 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 + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_GCJ \ + CC_GCJ \ + LD_GCJ \ + lt_prog_compiler_wl_GCJ \ + lt_prog_compiler_pic_GCJ \ + lt_prog_compiler_static_GCJ \ + lt_prog_compiler_no_builtin_flag_GCJ \ + export_dynamic_flag_spec_GCJ \ + thread_safe_flag_spec_GCJ \ + whole_archive_flag_spec_GCJ \ + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ + module_cmds_GCJ | \ + module_expsym_cmds_GCJ | \ + old_archive_from_expsyms_cmds_GCJ | \ + export_symbols_cmds_GCJ | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_GCJ + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_GCJ + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_GCJ + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_GCJ + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_GCJ + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_GCJ +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_GCJ + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_GCJ +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_GCJ +archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_GCJ +module_expsym_cmds=$lt_module_expsym_cmds_GCJ + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_GCJ + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_GCJ + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + +# 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. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_GCJ + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_GCJ + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +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 in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_GCJ + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ + +# 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_GCJ + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_GCJ + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_GCJ + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_GCJ + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_GCJ + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_GCJ" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_GCJ + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_GCJ + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_GCJ + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_GCJ + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +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 + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + RC) + + + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +objext_RC=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +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-%%"` + +lt_cv_prog_compiler_c_o_RC=yes + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # 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 + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_RC \ + CC_RC \ + LD_RC \ + lt_prog_compiler_wl_RC \ + lt_prog_compiler_pic_RC \ + lt_prog_compiler_static_RC \ + lt_prog_compiler_no_builtin_flag_RC \ + export_dynamic_flag_spec_RC \ + thread_safe_flag_spec_RC \ + whole_archive_flag_spec_RC \ + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ + module_cmds_RC | \ + module_expsym_cmds_RC | \ + old_archive_from_expsyms_cmds_RC | \ + export_symbols_cmds_RC | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_RC + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_RC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_RC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_RC + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_RC + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_RC +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_RC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_RC +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_RC +archive_expsym_cmds=$lt_archive_expsym_cmds_RC +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_RC +module_expsym_cmds=$lt_module_expsym_cmds_RC + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_RC + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_RC + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_RC + +# 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. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_RC + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_RC + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +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 in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_RC + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC + +# 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_RC + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_RC + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_RC + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_RC + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_RC + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_RC + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_RC" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_RC + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_RC + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_RC + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_RC + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +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 + +CC="$lt_save_CC" + + ;; + + *) + { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 +echo "$as_me: error: Unsupported tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 +echo "$as_me: error: unable to update list of available tagged configurations." >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Prevent multiple expansion + + + + + + + + + + + + + + + + + + + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +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/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_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. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +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 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + + +######### +# Set up an appropriate program prefix +# +if test "$program_prefix" = "NONE"; then + program_prefix="" +fi + + +VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'` +echo "Version set to $VERSION" + +RELEASE=`cat $srcdir/VERSION` +echo "Release set to $RELEASE" + +VERSION_NUMBER=`cat $srcdir/VERSION \ + | sed 's/[^0-9]/ /g' \ + | awk '{printf "%d%03d%03d",$1,$2,$3}'` +echo "Version number set to $VERSION_NUMBER" + + +######### +# Check to see if the --with-hints=FILE option is used. If there is none, +# then check for a files named "$host.hints" and ../$hosts.hints where +# $host is the hostname of the build system. If still no hints are +# found, try looking in $system.hints and ../$system.hints where +# $system is the result of uname -s. +# + +# Check whether --with-hints or --without-hints was given. +if test "${with_hints+set}" = set; then + withval="$with_hints" + hints=$withval +fi; +if test "$hints" = ""; then + host=`hostname | sed 's/\..*//'` + if test -r $host.hints; then + hints=$host.hints + else + if test -r ../$host.hints; then + hints=../$host.hints + fi + fi +fi +if test "$hints" = ""; then + sys=`uname -s` + if test -r $sys.hints; then + hints=$sys.hints + else + if test -r ../$sys.hints; then + hints=../$sys.hints + fi + fi +fi +if test "$hints" != ""; then + echo "$as_me:$LINENO: result: reading hints from $hints" >&5 +echo "${ECHO_T}reading hints from $hints" >&6 + . $hints +fi + +######### +# Locate a compiler for the build machine. This compiler should +# generate command-line programs that run on the build machine. +# +if test x"$cross_compiling" = xno; then + BUILD_CC=$CC + BUILD_CFLAGS=$CFLAGS +else + if test "${BUILD_CC+set}" != set; then + for ac_prog in gcc cc cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_BUILD_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # 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_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_BUILD_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + echo "$as_me:$LINENO: result: $BUILD_CC" >&5 +echo "${ECHO_T}$BUILD_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$BUILD_CC" && break +done + + fi + if test "${BUILD_CFLAGS+set}" != set; then + BUILD_CFLAGS="-g" + fi +fi + + + +########## +# Do we want to support multithreaded use of sqlite +# +# Check whether --enable-threadsafe or --disable-threadsafe was given. +if test "${enable_threadsafe+set}" = set; then + enableval="$enable_threadsafe" + +else + enable_threadsafe=yes +fi; +echo "$as_me:$LINENO: checking whether to support threadsafe operation" >&5 +echo $ECHO_N "checking whether to support threadsafe operation... $ECHO_C" >&6 +if test "$enable_threadsafe" = "no"; then + SQLITE_THREADSAFE=0 + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + SQLITE_THREADSAFE=1 + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +if test "$SQLITE_THREADSAFE" = "1"; then + LIBS="" + +echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 +echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6 +if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char pthread_create (); +int +main () +{ +pthread_create (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_pthread_pthread_create=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pthread_pthread_create=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 +echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6 +if test $ac_cv_lib_pthread_pthread_create = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +fi + + TARGET_THREAD_LIB="$LIBS" + LIBS="" +else + TARGET_THREAD_LIB="" +fi + + +########## +# Do we want to allow a connection created in one thread to be used +# in another thread. This does not work on many Linux systems (ex: RedHat 9) +# due to bugs in the threading implementations. This is thus off by default. +# +# Check whether --enable-cross-thread-connections or --disable-cross-thread-connections was given. +if test "${enable_cross_thread_connections+set}" = set; then + enableval="$enable_cross_thread_connections" + +else + enable_xthreadconnect=no +fi; +echo "$as_me:$LINENO: checking whether to allow connections to be shared across threads" >&5 +echo $ECHO_N "checking whether to allow connections to be shared across threads... $ECHO_C" >&6 +if test "$enable_xthreadconnect" = "no"; then + XTHREADCONNECT='' + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + XTHREADCONNECT='-DSQLITE_ALLOW_XTHREAD_CONNECT=1' + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +########## +# Do we want to set threadsOverrideEachOthersLocks variable to be 1 (true) by +# default. Normally, a test at runtime is performed to determine the +# appropriate value of this variable. Use this option only if you're sure that +# threads can safely override each others locks in all runtime situations. +# +# Check whether --enable-threads-override-locks or --disable-threads-override-locks was given. +if test "${enable_threads_override_locks+set}" = set; then + enableval="$enable_threads_override_locks" + +else + enable_threads_override_locks=no +fi; +echo "$as_me:$LINENO: checking whether threads can override each others locks" >&5 +echo $ECHO_N "checking whether threads can override each others locks... $ECHO_C" >&6 +if test "$enable_threads_override_locks" = "no"; then + THREADSOVERRIDELOCKS='-1' + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + THREADSOVERRIDELOCKS='1' + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +########## +# Do we want to support release +# +# Check whether --enable-releasemode or --disable-releasemode was given. +if test "${enable_releasemode+set}" = set; then + enableval="$enable_releasemode" + +else + enable_releasemode=no +fi; +echo "$as_me:$LINENO: checking whether to support shared library linked as release mode or not" >&5 +echo $ECHO_N "checking whether to support shared library linked as release mode or not... $ECHO_C" >&6 +if test "$enable_releasemode" = "no"; then + ALLOWRELEASE="" + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + ALLOWRELEASE="-release `cat $srcdir/VERSION`" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +fi + + +########## +# Do we want temporary databases in memory +# +# Check whether --enable-tempstore or --disable-tempstore was given. +if test "${enable_tempstore+set}" = set; then + enableval="$enable_tempstore" + +else + enable_tempstore=no +fi; +echo "$as_me:$LINENO: checking whether to use an in-ram database for temporary tables" >&5 +echo $ECHO_N "checking whether to use an in-ram database for temporary tables... $ECHO_C" >&6 +case "$enable_tempstore" in + never ) + TEMP_STORE=0 + echo "$as_me:$LINENO: result: never" >&5 +echo "${ECHO_T}never" >&6 + ;; + no ) + TEMP_STORE=1 + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + ;; + always ) + TEMP_STORE=3 + echo "$as_me:$LINENO: result: always" >&5 +echo "${ECHO_T}always" >&6 + ;; + yes ) + TEMP_STORE=3 + echo "$as_me:$LINENO: result: always" >&5 +echo "${ECHO_T}always" >&6 + ;; + * ) + TEMP_STORE=1 + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + ;; +esac + + + +########### +# Lots of things are different if we are compiling for Windows using +# the CYGWIN environment. So check for that special case and handle +# things accordingly. +# +echo "$as_me:$LINENO: checking if executables have the .exe suffix" >&5 +echo $ECHO_N "checking if executables have the .exe suffix... $ECHO_C" >&6 +if test "$config_BUILD_EXEEXT" = ".exe"; then + CYGWIN=yes + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: unknown" >&5 +echo "${ECHO_T}unknown" >&6 +fi +if test "$CYGWIN" != "yes"; then + +case $host_os in + *cygwin* ) CYGWIN=yes;; + * ) CYGWIN=no;; +esac + +fi +if test "$CYGWIN" = "yes"; then + BUILD_EXEEXT=.exe +else + BUILD_EXEEXT=$EXEEXT +fi +if test x"$cross_compiling" = xno; then + TARGET_EXEEXT=$BUILD_EXEEXT +else + TARGET_EXEEXT=$config_TARGET_EXEEXT +fi +if test "$TARGET_EXEEXT" = ".exe"; then + if test $OS2_SHELL ; then + OS_UNIX=0 + OS_WIN=0 + OS_OS2=1 + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_OS2=1" + if test "$ac_compiler_gnu" == "yes" ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Zomf -Zexe -Zmap" + BUILD_CFLAGS="$BUILD_CFLAGS -Zomf -Zexe" + fi + else + OS_UNIX=0 + OS_WIN=1 + OS_OS2=0 + tclsubdir=win + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" + fi +else + OS_UNIX=1 + OS_WIN=0 + OS_OS2=0 + tclsubdir=unix + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1" +fi + + + + + + + +########## +# Figure out all the parameters needed to compile against Tcl. +# +# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG +# macros in the in the tcl.m4 file of the standard TCL distribution. +# Those macros could not be used directly since we have to make some +# minor changes to accomodate systems that do not have TCL installed. +# +# Check whether --enable-tcl or --disable-tcl was given. +if test "${enable_tcl+set}" = set; then + enableval="$enable_tcl" + use_tcl=$enableval +else + use_tcl=yes +fi; +if test "${use_tcl}" = "yes" ; then + +# Check whether --with-tcl or --without-tcl was given. +if test "${with_tcl+set}" = set; then + withval="$with_tcl" + with_tclconfig=${withval} +fi; + echo "$as_me:$LINENO: checking for Tcl configuration" >&5 +echo $ECHO_N "checking for Tcl configuration... $ECHO_C" >&6 + if test "${ac_cv_c_tclconfig+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` + else + { { echo "$as_me:$LINENO: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&5 +echo "$as_me: error: ${with_tclconfig} directory doesn't contain tclConfig.sh" >&2;} + { (exit 1); exit 1; }; } + fi + fi + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` + do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + `ls -d ${libdir} 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` + do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i; pwd)` + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` + do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + use_tcl=no + { echo "$as_me:$LINENO: WARNING: Can't find Tcl configuration definitions" >&5 +echo "$as_me: WARNING: Can't find Tcl configuration definitions" >&2;} + { echo "$as_me:$LINENO: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&5 +echo "$as_me: WARNING: *** Without Tcl the regression tests cannot be executed ***" >&2;} + { echo "$as_me:$LINENO: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&5 +echo "$as_me: WARNING: *** Consider using --with-tcl=... to define location of Tcl ***" >&2;} + else + TCL_BIN_DIR=${ac_cv_c_tclconfig} + echo "$as_me:$LINENO: result: found $TCL_BIN_DIR/tclConfig.sh" >&5 +echo "${ECHO_T}found $TCL_BIN_DIR/tclConfig.sh" >&6 + + echo "$as_me:$LINENO: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5 +echo $ECHO_N "checking for existence of $TCL_BIN_DIR/tclConfig.sh... $ECHO_C" >&6 + if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then + echo "$as_me:$LINENO: result: loading" >&5 +echo "${ECHO_T}loading" >&6 + . $TCL_BIN_DIR/tclConfig.sh + else + echo "$as_me:$LINENO: result: file not found" >&5 +echo "${ECHO_T}file not found" >&6 + fi + + # + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + # + + if test -f $TCL_BIN_DIR/Makefile ; then + TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC} + TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC} + TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH} + fi + + # + # eval is required to do the TCL_DBGX substitution + # + + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + + + + + + + + + + + + + + fi +fi +if test "${use_tcl}" = "no" ; then + HAVE_TCL="" +else + HAVE_TCL=1 +fi + + +########## +# Figure out what C libraries are required to compile programs +# that use "readline()" library. +# +TARGET_READLINE_LIBS="" +TARGET_READLINE_INC="" +TARGET_HAVE_READLINE=0 +# Check whether --enable-readline or --disable-readline was given. +if test "${enable_readline+set}" = set; then + enableval="$enable_readline" + with_readline=$enableval +else + with_readline=auto +fi; + +if test x"$with_readline" != xno; then + found="yes" + + +# Check whether --with-readline-lib or --without-readline-lib was given. +if test "${with_readline_lib+set}" = set; then + withval="$with_readline_lib" + with_readline_lib=$withval +else + with_readline_lib="auto" +fi; + if test "x$with_readline_lib" = xauto; then + save_LIBS="$LIBS" + LIBS="" + echo "$as_me:$LINENO: checking for library containing tgetent" >&5 +echo $ECHO_N "checking for library containing tgetent... $ECHO_C" >&6 +if test "${ac_cv_search_tgetent+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_tgetent=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_tgetent="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_tgetent" = no; then + for ac_lib in readline ncurses curses termcap; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent (); +int +main () +{ +tgetent (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_tgetent="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_tgetent" >&5 +echo "${ECHO_T}$ac_cv_search_tgetent" >&6 +if test "$ac_cv_search_tgetent" != no; then + test "$ac_cv_search_tgetent" = "none required" || LIBS="$ac_cv_search_tgetent $LIBS" + term_LIBS="$LIBS" +else + term_LIBS="" +fi + + echo "$as_me:$LINENO: checking for readline in -lreadline" >&5 +echo $ECHO_N "checking for readline in -lreadline... $ECHO_C" >&6 +if test "${ac_cv_lib_readline_readline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char readline (); +int +main () +{ +readline (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_readline_readline=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_readline_readline=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_readline_readline" >&5 +echo "${ECHO_T}$ac_cv_lib_readline_readline" >&6 +if test $ac_cv_lib_readline_readline = yes; then + TARGET_READLINE_LIBS="-lreadline" +else + found="no" +fi + + TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS" + LIBS="$save_LIBS" + else + TARGET_READLINE_LIBS="$with_readline_lib" + fi + + +# Check whether --with-readline-inc or --without-readline-inc was given. +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 + echo "$as_me:$LINENO: checking for readline.h" >&5 +echo $ECHO_N "checking for readline.h... $ECHO_C" >&6 +if test "${ac_cv_header_readline_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_readline_h" >&5 +echo "${ECHO_T}$ac_cv_header_readline_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking readline.h usability" >&5 +echo $ECHO_N "checking readline.h usability... $ECHO_C" >&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 { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking readline.h presence" >&5 +echo $ECHO_N "checking readline.h presence... $ECHO_C" >&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 { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + 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 +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: readline.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: readline.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: readline.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: readline.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: readline.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: readline.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: readline.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: readline.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: readline.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: readline.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: readline.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: readline.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: readline.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: readline.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: readline.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: readline.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------------ ## +## Report this to the AC_PACKAGE_NAME lists. ## +## ------------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for readline.h" >&5 +echo $ECHO_N "checking for readline.h... $ECHO_C" >&6 +if test "${ac_cv_header_readline_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_readline_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_readline_h" >&5 +echo "${ECHO_T}$ac_cv_header_readline_h" >&6 + +fi +if test $ac_cv_header_readline_h = yes; then + found="yes" +else + + found="no" + if test "$cross_compiling" != yes; then + for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do + for subdir in include include/readline; do + as_ac_File=`echo "ac_cv_file_$dir/$subdir/readline.h" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $dir/$subdir/readline.h" >&5 +echo $ECHO_N "checking for $dir/$subdir/readline.h... $ECHO_C" >&6 +if eval "test \"\${$as_ac_File+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + test "$cross_compiling" = yes && + { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5 +echo "$as_me: error: cannot check for file existence when cross compiling" >&2;} + { (exit 1); exit 1; }; } +if test -r "$dir/$subdir/readline.h"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_File'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_File'}'`" >&6 +if test `eval echo '${'$as_ac_File'}'` = yes; then + found=yes +fi + + if test "$found" = "yes"; then + TARGET_READLINE_INC="-I$dir/$subdir" + break + fi + done + test "$found" = "yes" && break + done + fi + +fi + + + else + TARGET_READLINE_INC="$with_readline_inc" + fi + + if test x"$found" = xno; then + TARGET_READLINE_LIBS="" + TARGET_READLINE_INC="" + TARGET_HAVE_READLINE=0 + else + TARGET_HAVE_READLINE=1 + fi +fi + + + + + +########## +# Figure out what C libraries are required to compile programs +# that use "fdatasync()" function. +# +echo "$as_me:$LINENO: checking for library containing fdatasync" >&5 +echo $ECHO_N "checking for library containing fdatasync... $ECHO_C" >&6 +if test "${ac_cv_search_fdatasync+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +ac_cv_search_fdatasync=no +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fdatasync (); +int +main () +{ +fdatasync (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_fdatasync="none required" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test "$ac_cv_search_fdatasync" = no; then + for ac_lib in rt; do + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fdatasync (); +int +main () +{ +fdatasync (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_fdatasync="-l$ac_lib" +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + done +fi +LIBS=$ac_func_search_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_search_fdatasync" >&5 +echo "${ECHO_T}$ac_cv_search_fdatasync" >&6 +if test "$ac_cv_search_fdatasync" != no; then + test "$ac_cv_search_fdatasync" = "none required" || LIBS="$ac_cv_search_fdatasync $LIBS" + +fi + + +######### +# check for debug enabled +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + use_debug=$enableval +else + use_debug=no +fi; +if test "${use_debug}" = "yes" ; then + TARGET_DEBUG="-DSQLITE_DEBUG=1" +else + TARGET_DEBUG="-DNDEBUG" +fi + + +######### +# Figure out whether or not we have a "usleep()" function. +# +echo "$as_me:$LINENO: checking for usleep" >&5 +echo $ECHO_N "checking for usleep... $ECHO_C" >&6 +if test "${ac_cv_func_usleep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 usleep to an innocuous variant, in case declares usleep. + For example, HP-UX 11i declares gettimeofday. */ +#define usleep innocuous_usleep + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char usleep (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef usleep + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char usleep (); +/* 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_usleep) || defined (__stub___usleep) +choke me +#else +char (*f) () = usleep; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != usleep; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_usleep=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_usleep=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_usleep" >&5 +echo "${ECHO_T}$ac_cv_func_usleep" >&6 +if test $ac_cv_func_usleep = yes; then + TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_USLEEP=1" +fi + + +#-------------------------------------------------------------------- +# Redefine fdatasync as fsync on systems that lack fdatasync +#-------------------------------------------------------------------- + +echo "$as_me:$LINENO: checking for fdatasync" >&5 +echo $ECHO_N "checking for fdatasync... $ECHO_C" >&6 +if test "${ac_cv_func_fdatasync+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 fdatasync to an innocuous variant, in case declares fdatasync. + For example, HP-UX 11i declares gettimeofday. */ +#define fdatasync innocuous_fdatasync + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char fdatasync (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef fdatasync + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fdatasync (); +/* 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_fdatasync) || defined (__stub___fdatasync) +choke me +#else +char (*f) () = fdatasync; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != fdatasync; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_fdatasync=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_fdatasync=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_fdatasync" >&5 +echo "${ECHO_T}$ac_cv_func_fdatasync" >&6 +if test $ac_cv_func_fdatasync = yes; then + TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_FDATASYNC=1" +fi + + +######### +# Generate the output files. +# + ac_config_files="$ac_config_files Makefile sqlite3.pc" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `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" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\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" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ 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/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# 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+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi +DUALCASE=1; export DUALCASE # for MKS sh + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# 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 + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + 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 + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + 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=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # 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 before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, 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 + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +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 sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# 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'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.59. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet 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] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.59, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2003 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +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=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + + + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "sqlite3.pc" ) CONFIG_FILES="$CONFIG_FILES sqlite3.pc" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@EGREP@,$EGREP,;t t +s,@LN_S@,$LN_S,;t t +s,@ECHO@,$ECHO,;t t +s,@AR@,$AR,;t t +s,@ac_ct_AR@,$ac_ct_AR,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@CPP@,$CPP,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@F77@,$F77,;t t +s,@FFLAGS@,$FFLAGS,;t t +s,@ac_ct_F77@,$ac_ct_F77,;t t +s,@LIBTOOL@,$LIBTOOL,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@AWK@,$AWK,;t t +s,@program_prefix@,$program_prefix,;t t +s,@VERSION@,$VERSION,;t t +s,@RELEASE@,$RELEASE,;t t +s,@VERSION_NUMBER@,$VERSION_NUMBER,;t t +s,@BUILD_CC@,$BUILD_CC,;t t +s,@BUILD_CFLAGS@,$BUILD_CFLAGS,;t t +s,@SQLITE_THREADSAFE@,$SQLITE_THREADSAFE,;t t +s,@TARGET_THREAD_LIB@,$TARGET_THREAD_LIB,;t t +s,@XTHREADCONNECT@,$XTHREADCONNECT,;t t +s,@THREADSOVERRIDELOCKS@,$THREADSOVERRIDELOCKS,;t t +s,@ALLOWRELEASE@,$ALLOWRELEASE,;t t +s,@TEMP_STORE@,$TEMP_STORE,;t t +s,@BUILD_EXEEXT@,$BUILD_EXEEXT,;t t +s,@OS_UNIX@,$OS_UNIX,;t t +s,@OS_WIN@,$OS_WIN,;t t +s,@OS_OS2@,$OS_OS2,;t t +s,@TARGET_EXEEXT@,$TARGET_EXEEXT,;t t +s,@TCL_VERSION@,$TCL_VERSION,;t t +s,@TCL_BIN_DIR@,$TCL_BIN_DIR,;t t +s,@TCL_SRC_DIR@,$TCL_SRC_DIR,;t t +s,@TCL_LIBS@,$TCL_LIBS,;t t +s,@TCL_INCLUDE_SPEC@,$TCL_INCLUDE_SPEC,;t t +s,@TCL_LIB_FILE@,$TCL_LIB_FILE,;t t +s,@TCL_LIB_FLAG@,$TCL_LIB_FLAG,;t t +s,@TCL_LIB_SPEC@,$TCL_LIB_SPEC,;t t +s,@TCL_STUB_LIB_FILE@,$TCL_STUB_LIB_FILE,;t t +s,@TCL_STUB_LIB_FLAG@,$TCL_STUB_LIB_FLAG,;t t +s,@TCL_STUB_LIB_SPEC@,$TCL_STUB_LIB_SPEC,;t t +s,@HAVE_TCL@,$HAVE_TCL,;t t +s,@TARGET_READLINE_LIBS@,$TARGET_READLINE_LIBS,;t t +s,@TARGET_READLINE_INC@,$TARGET_READLINE_INC,;t t +s,@TARGET_HAVE_READLINE@,$TARGET_HAVE_READLINE,;t t +s,@TARGET_DEBUG@,$TARGET_DEBUG,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo "$f";; + *) # Relative + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + 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; } +fi + diff --git a/client/src/thirdparty/sqlite-3.4.2/configure.ac b/client/src/thirdparty/sqlite-3.4.2/configure.ac new file mode 100644 index 0000000..1bb2169 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/configure.ac @@ -0,0 +1,582 @@ +# +# The build process allows for using a cross-compiler. But the default +# action is to target the same platform that we are running on. The +# configure script needs to discover the following properties of the +# build and target systems: +# +# srcdir +# +# The is the name of the directory that contains the +# "configure" shell script. All source files are +# located relative to this directory. +# +# bindir +# +# The name of the directory where executables should be +# written by the "install" target of the makefile. +# +# program_prefix +# +# Add this prefix to the names of all executables that run +# on the target machine. Default: "" +# +# ENABLE_SHARED +# +# True if shared libraries should be generated. +# +# BUILD_CC +# +# The name of a command that is used to convert C +# source files into executables that run on the build +# platform. +# +# BUILD_CFLAGS +# +# Switches that the build compiler needs in order to construct +# command-line programs. +# +# BUILD_LIBS +# +# Libraries that the build compiler needs in order to construct +# command-line programs. +# +# BUILD_EXEEXT +# +# The filename extension for executables on the build +# platform. "" for Unix and ".exe" for Windows. +# +# TCL_* +# +# Lots of values are read in from the tclConfig.sh script, +# if that script is available. This values are used for +# constructing and installing the TCL extension. +# +# TARGET_READLINE_LIBS +# +# This is the library directives passed to the target linker +# that cause the executable to link against the readline library. +# This might be a switch like "-lreadline" or pathnames of library +# file like "../../src/libreadline.a". +# +# TARGET_READLINE_INC +# +# This variables define the directory that contain header +# files for the readline library. If the compiler is able +# to find on its own, then this can be blank. +# +# TARGET_EXEEXT +# +# The filename extension for executables on the +# target platform. "" for Unix and ".exe" for windows. +# +# The generated configure script will make an attempt to guess +# at all of the above parameters. You can override any of +# the guesses by setting the environment variable named +# "config_AAAA" where "AAAA" is the name of the parameter +# described above. (Exception: srcdir cannot be set this way.) +# If you have a file that sets one or more of these environment +# variables, you can invoke configure as follows: +# +# configure --with-hints=FILE +# +# where FILE is the name of the file that sets the environment +# variables. FILE should be an absolute pathname. +# +# This configure.in file is easy to reuse on other projects. Just +# change the argument to AC_INIT(). And disable any features that +# you don't need (for example BLT) by erasing or commenting out +# the corresponding code. +# +AC_INIT(src/sqlite.h.in) + +dnl Put the RCS revision string after AC_INIT so that it will also +dnl show in in configure. +# The following RCS revision string applies to configure.in +# $Revision: 1.31 $ + +######### +# Programs needed +# +AC_PROG_LIBTOOL +AC_PROG_INSTALL +AC_PROG_AWK + +######### +# Set up an appropriate program prefix +# +if test "$program_prefix" = "NONE"; then + program_prefix="" +fi +AC_SUBST(program_prefix) + +VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`] +echo "Version set to $VERSION" +AC_SUBST(VERSION) +RELEASE=`cat $srcdir/VERSION` +echo "Release set to $RELEASE" +AC_SUBST(RELEASE) +VERSION_NUMBER=[`cat $srcdir/VERSION \ + | sed 's/[^0-9]/ /g' \ + | awk '{printf "%d%03d%03d",$1,$2,$3}'`] +echo "Version number set to $VERSION_NUMBER" +AC_SUBST(VERSION_NUMBER) + +######### +# Check to see if the --with-hints=FILE option is used. If there is none, +# then check for a files named "$host.hints" and ../$hosts.hints where +# $host is the hostname of the build system. If still no hints are +# found, try looking in $system.hints and ../$system.hints where +# $system is the result of uname -s. +# +AC_ARG_WITH(hints, + AC_HELP_STRING([--with-hints=FILE],[Read configuration options from FILE]), + hints=$withval) +if test "$hints" = ""; then + host=`hostname | sed 's/\..*//'` + if test -r $host.hints; then + hints=$host.hints + else + if test -r ../$host.hints; then + hints=../$host.hints + fi + fi +fi +if test "$hints" = ""; then + sys=`uname -s` + if test -r $sys.hints; then + hints=$sys.hints + else + if test -r ../$sys.hints; then + hints=../$sys.hints + fi + fi +fi +if test "$hints" != ""; then + AC_MSG_RESULT(reading hints from $hints) + . $hints +fi + +######### +# Locate a compiler for the build machine. This compiler should +# generate command-line programs that run on the build machine. +# +if test x"$cross_compiling" = xno; then + BUILD_CC=$CC + BUILD_CFLAGS=$CFLAGS +else + if test "${BUILD_CC+set}" != set; then + AC_CHECK_PROGS(BUILD_CC, gcc cc cl) + fi + if test "${BUILD_CFLAGS+set}" != set; then + BUILD_CFLAGS="-g" + fi +fi +AC_SUBST(BUILD_CC) +AC_SUBST(BUILD_CFLAGS) + +########## +# Do we want to support multithreaded use of sqlite +# +AC_ARG_ENABLE(threadsafe, +AC_HELP_STRING([--enable-threadsafe],[Support threadsafe operation]),,enable_threadsafe=yes) +AC_MSG_CHECKING([whether to support threadsafe operation]) +if test "$enable_threadsafe" = "no"; then + SQLITE_THREADSAFE=0 + AC_MSG_RESULT([no]) +else + SQLITE_THREADSAFE=1 + AC_MSG_RESULT([yes]) +fi +AC_SUBST(SQLITE_THREADSAFE) + +if test "$SQLITE_THREADSAFE" = "1"; then + LIBS="" + AC_CHECK_LIB(pthread, pthread_create) + TARGET_THREAD_LIB="$LIBS" + LIBS="" +else + TARGET_THREAD_LIB="" +fi +AC_SUBST(TARGET_THREAD_LIB) + +########## +# Do we want to allow a connection created in one thread to be used +# in another thread. This does not work on many Linux systems (ex: RedHat 9) +# due to bugs in the threading implementations. This is thus off by default. +# +AC_ARG_ENABLE(cross-thread-connections, +AC_HELP_STRING([--enable-cross-thread-connections],[Allow connection sharing across threads]),,enable_xthreadconnect=no) +AC_MSG_CHECKING([whether to allow connections to be shared across threads]) +if test "$enable_xthreadconnect" = "no"; then + XTHREADCONNECT='' + AC_MSG_RESULT([no]) +else + XTHREADCONNECT='-DSQLITE_ALLOW_XTHREAD_CONNECT=1' + AC_MSG_RESULT([yes]) +fi +AC_SUBST(XTHREADCONNECT) + +########## +# Do we want to set threadsOverrideEachOthersLocks variable to be 1 (true) by +# default. Normally, a test at runtime is performed to determine the +# appropriate value of this variable. Use this option only if you're sure that +# threads can safely override each others locks in all runtime situations. +# +AC_ARG_ENABLE(threads-override-locks, +AC_HELP_STRING([--enable-threads-override-locks],[Threads can override each others locks]),,enable_threads_override_locks=no) +AC_MSG_CHECKING([whether threads can override each others locks]) +if test "$enable_threads_override_locks" = "no"; then + THREADSOVERRIDELOCKS='-1' + AC_MSG_RESULT([no]) +else + THREADSOVERRIDELOCKS='1' + AC_MSG_RESULT([yes]) +fi +AC_SUBST(THREADSOVERRIDELOCKS) + +########## +# Do we want to support release +# +AC_ARG_ENABLE(releasemode, +AC_HELP_STRING([--enable-releasemode],[Support libtool link to release mode]),,enable_releasemode=no) +AC_MSG_CHECKING([whether to support shared library linked as release mode or not]) +if test "$enable_releasemode" = "no"; then + ALLOWRELEASE="" + AC_MSG_RESULT([no]) +else + ALLOWRELEASE="-release `cat $srcdir/VERSION`" + AC_MSG_RESULT([yes]) +fi +AC_SUBST(ALLOWRELEASE) + +########## +# Do we want temporary databases in memory +# +AC_ARG_ENABLE(tempstore, +AC_HELP_STRING([--enable-tempstore],[Use an in-ram database for temporary tables (never,no,yes,always)]),,enable_tempstore=no) +AC_MSG_CHECKING([whether to use an in-ram database for temporary tables]) +case "$enable_tempstore" in + never ) + TEMP_STORE=0 + AC_MSG_RESULT([never]) + ;; + no ) + TEMP_STORE=1 + AC_MSG_RESULT([no]) + ;; + always ) + TEMP_STORE=3 + AC_MSG_RESULT([always]) + ;; + yes ) + TEMP_STORE=3 + AC_MSG_RESULT([always]) + ;; + * ) + TEMP_STORE=1 + AC_MSG_RESULT([yes]) + ;; +esac + +AC_SUBST(TEMP_STORE) + +########### +# Lots of things are different if we are compiling for Windows using +# the CYGWIN environment. So check for that special case and handle +# things accordingly. +# +AC_MSG_CHECKING([if executables have the .exe suffix]) +if test "$config_BUILD_EXEEXT" = ".exe"; then + CYGWIN=yes + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(unknown) +fi +if test "$CYGWIN" != "yes"; then + AC_CYGWIN +fi +if test "$CYGWIN" = "yes"; then + BUILD_EXEEXT=.exe +else + BUILD_EXEEXT=$EXEEXT +fi +if test x"$cross_compiling" = xno; then + TARGET_EXEEXT=$BUILD_EXEEXT +else + TARGET_EXEEXT=$config_TARGET_EXEEXT +fi +if test "$TARGET_EXEEXT" = ".exe"; then + if test $OS2_SHELL ; then + OS_UNIX=0 + OS_WIN=0 + OS_OS2=1 + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_OS2=1" + if test "$ac_compiler_gnu" == "yes" ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Zomf -Zexe -Zmap" + BUILD_CFLAGS="$BUILD_CFLAGS -Zomf -Zexe" + fi + else + OS_UNIX=0 + OS_WIN=1 + OS_OS2=0 + tclsubdir=win + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_WIN=1" + fi +else + OS_UNIX=1 + OS_WIN=0 + OS_OS2=0 + tclsubdir=unix + TARGET_CFLAGS="$TARGET_CFLAGS -DOS_UNIX=1" +fi + +AC_SUBST(BUILD_EXEEXT) +AC_SUBST(OS_UNIX) +AC_SUBST(OS_WIN) +AC_SUBST(OS_OS2) +AC_SUBST(TARGET_EXEEXT) + +########## +# Figure out all the parameters needed to compile against Tcl. +# +# This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG +# macros in the in the tcl.m4 file of the standard TCL distribution. +# Those macros could not be used directly since we have to make some +# minor changes to accomodate systems that do not have TCL installed. +# +AC_ARG_ENABLE(tcl, AC_HELP_STRING([--disable-tcl],[do not build TCL extension]), + [use_tcl=$enableval],[use_tcl=yes]) +if test "${use_tcl}" = "yes" ; then + AC_ARG_WITH(tcl, AC_HELP_STRING([--with-tcl=DIR],[directory containing tcl configuration (tclConfig.sh)]), with_tclconfig=${withval}) + AC_MSG_CHECKING([for Tcl configuration]) + AC_CACHE_VAL(ac_cv_c_tclconfig,[ + # First check to see if --with-tcl was specified. + if test x"${with_tclconfig}" != x ; then + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` + else + AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) + fi + fi + # then check for a private Tcl installation + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ../tcl \ + `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../tcl \ + `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ + ../../../tcl \ + `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` + do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + `ls -d ${libdir} 2>/dev/null` \ + `ls -d /usr/local/lib 2>/dev/null` \ + `ls -d /usr/contrib/lib 2>/dev/null` \ + `ls -d /usr/lib 2>/dev/null` + do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i; pwd)` + break + fi + done + fi + + # check in a few other private locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in \ + ${srcdir}/../tcl \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ + `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` + do + if test -f "$i/unix/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i/unix; pwd)` + break + fi + done + fi + ]) + + if test x"${ac_cv_c_tclconfig}" = x ; then + use_tcl=no + AC_MSG_WARN(Can't find Tcl configuration definitions) + AC_MSG_WARN(*** Without Tcl the regression tests cannot be executed ***) + AC_MSG_WARN(*** Consider using --with-tcl=... to define location of Tcl ***) + else + TCL_BIN_DIR=${ac_cv_c_tclconfig} + AC_MSG_RESULT(found $TCL_BIN_DIR/tclConfig.sh) + + AC_MSG_CHECKING([for existence of $TCL_BIN_DIR/tclConfig.sh]) + if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then + AC_MSG_RESULT([loading]) + . $TCL_BIN_DIR/tclConfig.sh + else + AC_MSG_RESULT([file not found]) + fi + + # + # If the TCL_BIN_DIR is the build directory (not the install directory), + # then set the common variable name to the value of the build variables. + # For example, the variable TCL_LIB_SPEC will be set to the value + # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC + # instead of TCL_BUILD_LIB_SPEC since it will work with both an + # installed and uninstalled version of Tcl. + # + + if test -f $TCL_BIN_DIR/Makefile ; then + TCL_LIB_SPEC=${TCL_BUILD_LIB_SPEC} + TCL_STUB_LIB_SPEC=${TCL_BUILD_STUB_LIB_SPEC} + TCL_STUB_LIB_PATH=${TCL_BUILD_STUB_LIB_PATH} + fi + + # + # eval is required to do the TCL_DBGX substitution + # + + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + + eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" + eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" + eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" + + AC_SUBST(TCL_VERSION) + AC_SUBST(TCL_BIN_DIR) + AC_SUBST(TCL_SRC_DIR) + AC_SUBST(TCL_LIBS) + AC_SUBST(TCL_INCLUDE_SPEC) + + AC_SUBST(TCL_LIB_FILE) + AC_SUBST(TCL_LIB_FLAG) + AC_SUBST(TCL_LIB_SPEC) + + AC_SUBST(TCL_STUB_LIB_FILE) + AC_SUBST(TCL_STUB_LIB_FLAG) + AC_SUBST(TCL_STUB_LIB_SPEC) + fi +fi +if test "${use_tcl}" = "no" ; then + HAVE_TCL="" +else + HAVE_TCL=1 +fi +AC_SUBST(HAVE_TCL) + +########## +# Figure out what C libraries are required to compile programs +# that use "readline()" library. +# +TARGET_READLINE_LIBS="" +TARGET_READLINE_INC="" +TARGET_HAVE_READLINE=0 +AC_ARG_ENABLE([readline], + [AC_HELP_STRING([--disable-readline],[disable readline support [default=detect]])], + [with_readline=$enableval], + [with_readline=auto]) + +if test x"$with_readline" != xno; then + found="yes" + + AC_ARG_WITH([readline-lib], + [AC_HELP_STRING([--with-readline-lib],[specify readline library])], + [with_readline_lib=$withval], + [with_readline_lib="auto"]) + if test "x$with_readline_lib" = xauto; then + save_LIBS="$LIBS" + LIBS="" + AC_SEARCH_LIBS(tgetent, [readline ncurses curses termcap], [term_LIBS="$LIBS"], [term_LIBS=""]) + AC_CHECK_LIB([readline], [readline], [TARGET_READLINE_LIBS="-lreadline"], [found="no"]) + TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS" + LIBS="$save_LIBS" + else + TARGET_READLINE_LIBS="$with_readline_lib" + fi + + AC_ARG_WITH([readline-inc], + [AC_HELP_STRING([--with-readline-inc],[specify readline include paths])], + [with_readline_inc=$withval], + [with_readline_inc="auto"]) + if test "x$with_readline_inc" = xauto; then + AC_CHECK_HEADER(readline.h, [found="yes"], [ + found="no" + if test "$cross_compiling" != yes; then + for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do + for subdir in include include/readline; do + AC_CHECK_FILE($dir/$subdir/readline.h, found=yes) + if test "$found" = "yes"; then + TARGET_READLINE_INC="-I$dir/$subdir" + break + fi + done + test "$found" = "yes" && break + done + fi + ]) + else + TARGET_READLINE_INC="$with_readline_inc" + fi + + if test x"$found" = xno; then + TARGET_READLINE_LIBS="" + TARGET_READLINE_INC="" + TARGET_HAVE_READLINE=0 + else + TARGET_HAVE_READLINE=1 + fi +fi + +AC_SUBST(TARGET_READLINE_LIBS) +AC_SUBST(TARGET_READLINE_INC) +AC_SUBST(TARGET_HAVE_READLINE) + +########## +# Figure out what C libraries are required to compile programs +# that use "fdatasync()" function. +# +AC_SEARCH_LIBS(fdatasync, [rt]) + +######### +# check for debug enabled +AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain]), + [use_debug=$enableval],[use_debug=no]) +if test "${use_debug}" = "yes" ; then + TARGET_DEBUG="-DSQLITE_DEBUG=1" +else + TARGET_DEBUG="-DNDEBUG" +fi +AC_SUBST(TARGET_DEBUG) + +######### +# Figure out whether or not we have a "usleep()" function. +# +AC_CHECK_FUNC(usleep, [TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_USLEEP=1"]) + +#-------------------------------------------------------------------- +# Redefine fdatasync as fsync on systems that lack fdatasync +#-------------------------------------------------------------------- + +AC_CHECK_FUNC(fdatasync, [TARGET_CFLAGS="$TARGET_CFLAGS -DHAVE_FDATASYNC=1"]) + +######### +# Generate the output files. +# +AC_OUTPUT([ +Makefile +sqlite3.pc +]) diff --git a/client/src/thirdparty/sqlite-3.4.2/contrib/sqlitecon.tcl b/client/src/thirdparty/sqlite-3.4.2/contrib/sqlitecon.tcl new file mode 100644 index 0000000..b5dbcaf --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/contrib/sqlitecon.tcl @@ -0,0 +1,679 @@ +# A Tk console widget for SQLite. Invoke sqlitecon::create with a window name, +# a prompt string, a title to set a new top-level window, and the SQLite +# database handle. For example: +# +# sqlitecon::create .sqlcon {sql:- } {SQL Console} db +# +# A toplevel window is created that allows you to type in SQL commands to +# be processed on the spot. +# +# A limited set of dot-commands are supported: +# +# .table +# .schema ?TABLE? +# .mode list|column|multicolumn|line +# .exit +# +# In addition, a new SQL function named "edit()" is created. This function +# takes a single text argument and returns a text result. Whenever the +# the function is called, it pops up a new toplevel window containing a +# text editor screen initialized to the argument. When the "OK" button +# is pressed, whatever revised text is in the text editor is returned as +# the result of the edit() function. This allows text fields of SQL tables +# to be edited quickly and easily as follows: +# +# UPDATE table1 SET dscr = edit(dscr) WHERE rowid=15; +# + + +# Create a namespace to work in +# +namespace eval ::sqlitecon { + # do nothing +} + +# Create a console widget named $w. The prompt string is $prompt. +# The title at the top of the window is $title. The database connection +# object is $db +# +proc sqlitecon::create {w prompt title db} { + upvar #0 $w.t v + if {[winfo exists $w]} {destroy $w} + if {[info exists v]} {unset v} + toplevel $w + wm title $w $title + wm iconname $w $title + frame $w.mb -bd 2 -relief raised + pack $w.mb -side top -fill x + menubutton $w.mb.file -text File -menu $w.mb.file.m + menubutton $w.mb.edit -text Edit -menu $w.mb.edit.m + pack $w.mb.file $w.mb.edit -side left -padx 8 -pady 1 + set m [menu $w.mb.file.m -tearoff 0] + $m add command -label {Close} -command "destroy $w" + sqlitecon::create_child $w $prompt $w.mb.edit.m + set v(db) $db + $db function edit ::sqlitecon::_edit +} + +# This routine creates a console as a child window within a larger +# window. It also creates an edit menu named "$editmenu" if $editmenu!="". +# The calling function is responsible for posting the edit menu. +# +proc sqlitecon::create_child {w prompt editmenu} { + upvar #0 $w.t v + if {$editmenu!=""} { + set m [menu $editmenu -tearoff 0] + $m add command -label Cut -command "sqlitecon::Cut $w.t" + $m add command -label Copy -command "sqlitecon::Copy $w.t" + $m add command -label Paste -command "sqlitecon::Paste $w.t" + $m add command -label {Clear Screen} -command "sqlitecon::Clear $w.t" + $m add separator + $m add command -label {Save As...} -command "sqlitecon::SaveFile $w.t" + catch {$editmenu config -postcommand "sqlitecon::EnableEditMenu $w"} + } + scrollbar $w.sb -orient vertical -command "$w.t yview" + pack $w.sb -side right -fill y + text $w.t -font fixed -yscrollcommand "$w.sb set" + pack $w.t -side right -fill both -expand 1 + bindtags $w.t Sqlitecon + set v(editmenu) $editmenu + set v(history) 0 + set v(historycnt) 0 + set v(current) -1 + set v(prompt) $prompt + set v(prior) {} + set v(plength) [string length $v(prompt)] + set v(x) 0 + set v(y) 0 + set v(mode) column + set v(header) on + $w.t mark set insert end + $w.t tag config ok -foreground blue + $w.t tag config err -foreground red + $w.t insert end $v(prompt) + $w.t mark set out 1.0 + after idle "focus $w.t" +} + +bind Sqlitecon <1> {sqlitecon::Button1 %W %x %y} +bind Sqlitecon {sqlitecon::B1Motion %W %x %y} +bind Sqlitecon {sqlitecon::B1Leave %W %x %y} +bind Sqlitecon {sqlitecon::cancelMotor %W} +bind Sqlitecon {sqlitecon::cancelMotor %W} +bind Sqlitecon {sqlitecon::Insert %W %A} +bind Sqlitecon {sqlitecon::Left %W} +bind Sqlitecon {sqlitecon::Left %W} +bind Sqlitecon {sqlitecon::Right %W} +bind Sqlitecon {sqlitecon::Right %W} +bind Sqlitecon {sqlitecon::Backspace %W} +bind Sqlitecon {sqlitecon::Backspace %W} +bind Sqlitecon {sqlitecon::Delete %W} +bind Sqlitecon {sqlitecon::Delete %W} +bind Sqlitecon {sqlitecon::Home %W} +bind Sqlitecon {sqlitecon::Home %W} +bind Sqlitecon {sqlitecon::End %W} +bind Sqlitecon {sqlitecon::End %W} +bind Sqlitecon {sqlitecon::Enter %W} +bind Sqlitecon {sqlitecon::Enter %W} +bind Sqlitecon {sqlitecon::Prior %W} +bind Sqlitecon {sqlitecon::Prior %W} +bind Sqlitecon {sqlitecon::Next %W} +bind Sqlitecon {sqlitecon::Next %W} +bind Sqlitecon {sqlitecon::EraseEOL %W} +bind Sqlitecon <> {sqlitecon::Cut %W} +bind Sqlitecon <> {sqlitecon::Copy %W} +bind Sqlitecon <> {sqlitecon::Paste %W} +bind Sqlitecon <> {sqlitecon::Clear %W} + +# Insert a single character at the insertion cursor +# +proc sqlitecon::Insert {w a} { + $w insert insert $a + $w yview insert +} + +# Move the cursor one character to the left +# +proc sqlitecon::Left {w} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + if {$col>$v(plength)} { + $w mark set insert "insert -1c" + } +} + +# Erase the character to the left of the cursor +# +proc sqlitecon::Backspace {w} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + if {$col>$v(plength)} { + $w delete {insert -1c} + } +} + +# Erase to the end of the line +# +proc sqlitecon::EraseEOL {w} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + if {$col>=$v(plength)} { + $w delete insert {insert lineend} + } +} + +# Move the cursor one character to the right +# +proc sqlitecon::Right {w} { + $w mark set insert "insert +1c" +} + +# Erase the character to the right of the cursor +# +proc sqlitecon::Delete w { + $w delete insert +} + +# Move the cursor to the beginning of the current line +# +proc sqlitecon::Home w { + upvar #0 $w v + scan [$w index insert] %d.%d row col + $w mark set insert $row.$v(plength) +} + +# Move the cursor to the end of the current line +# +proc sqlitecon::End w { + $w mark set insert {insert lineend} +} + +# Add a line to the history +# +proc sqlitecon::addHistory {w line} { + upvar #0 $w v + if {$v(historycnt)>0} { + set last [lindex $v(history) [expr $v(historycnt)-1]] + if {[string compare $last $line]} { + lappend v(history) $line + incr v(historycnt) + } + } else { + set v(history) [list $line] + set v(historycnt) 1 + } + set v(current) $v(historycnt) +} + +# Called when "Enter" is pressed. Do something with the line +# of text that was entered. +# +proc sqlitecon::Enter w { + upvar #0 $w v + scan [$w index insert] %d.%d row col + set start $row.$v(plength) + set line [$w get $start "$start lineend"] + $w insert end \n + $w mark set out end + if {$v(prior)==""} { + set cmd $line + } else { + set cmd $v(prior)\n$line + } + if {[string index $cmd 0]=="." || [$v(db) complete $cmd]} { + regsub -all {\n} [string trim $cmd] { } cmd2 + addHistory $w $cmd2 + set rc [catch {DoCommand $w $cmd} res] + if {![winfo exists $w]} return + if {$rc} { + $w insert end $res\n err + } elseif {[string length $res]>0} { + $w insert end $res\n ok + } + set v(prior) {} + $w insert end $v(prompt) + } else { + set v(prior) $cmd + regsub -all {[^ ]} $v(prompt) . x + $w insert end $x + } + $w mark set insert end + $w mark set out {insert linestart} + $w yview insert +} + +# Execute a single SQL command. Pay special attention to control +# directives that begin with "." +# +# The return value is the text output from the command, properly +# formatted. +# +proc sqlitecon::DoCommand {w cmd} { + upvar #0 $w v + set mode $v(mode) + set header $v(header) + if {[regexp {^(\.[a-z]+)} $cmd all word]} { + if {$word==".mode"} { + regexp {^.[a-z]+ +([a-z]+)} $cmd all v(mode) + return {} + } elseif {$word==".exit"} { + destroy [winfo toplevel $w] + return {} + } elseif {$word==".header"} { + regexp {^.[a-z]+ +([a-z]+)} $cmd all v(header) + return {} + } elseif {$word==".tables"} { + set mode multicolumn + set cmd {SELECT name FROM sqlite_master WHERE type='table' + UNION ALL + SELECT name FROM sqlite_temp_master WHERE type='table'} + $v(db) eval {PRAGMA database_list} { + if {$name!="temp" && $name!="main"} { + append cmd "UNION ALL SELECT name FROM $name.sqlite_master\ + WHERE type='table'" + } + } + append cmd { ORDER BY 1} + } elseif {$word==".fullschema"} { + set pattern % + regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern + set mode list + set header 0 + set cmd "SELECT sql FROM sqlite_master WHERE tbl_name LIKE '$pattern' + AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master + WHERE tbl_name LIKE '$pattern' AND sql NOT NULL" + $v(db) eval {PRAGMA database_list} { + if {$name!="temp" && $name!="main"} { + append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\ + WHERE tbl_name LIKE '$pattern' AND sql NOT NULL" + } + } + } elseif {$word==".schema"} { + set pattern % + regexp {^.[a-z]+ +([^ ]+)} $cmd all pattern + set mode list + set header 0 + set cmd "SELECT sql FROM sqlite_master WHERE name LIKE '$pattern' + AND sql NOT NULL UNION ALL SELECT sql FROM sqlite_temp_master + WHERE name LIKE '$pattern' AND sql NOT NULL" + $v(db) eval {PRAGMA database_list} { + if {$name!="temp" && $name!="main"} { + append cmd " UNION ALL SELECT sql FROM $name.sqlite_master\ + WHERE name LIKE '$pattern' AND sql NOT NULL" + } + } + } else { + return \ + ".exit\n.mode line|list|column\n.schema ?TABLENAME?\n.tables" + } + } + set res {} + if {$mode=="list"} { + $v(db) eval $cmd x { + set sep {} + foreach col $x(*) { + append res $sep$x($col) + set sep | + } + append res \n + } + if {[info exists x(*)] && $header} { + set sep {} + set hdr {} + foreach col $x(*) { + append hdr $sep$col + set sep | + } + set res $hdr\n$res + } + } elseif {[string range $mode 0 2]=="col"} { + set y {} + $v(db) eval $cmd x { + foreach col $x(*) { + if {![info exists cw($col)] || $cw($col)<[string length $x($col)]} { + set cw($col) [string length $x($col)] + } + lappend y $x($col) + } + } + if {[info exists x(*)] && $header} { + set hdr {} + set ln {} + set dash --------------------------------------------------------------- + append dash ------------------------------------------------------------ + foreach col $x(*) { + if {![info exists cw($col)] || $cw($col)<[string length $col]} { + set cw($col) [string length $col] + } + lappend hdr $col + lappend ln [string range $dash 1 $cw($col)] + } + set y [concat $hdr $ln $y] + } + if {[info exists x(*)]} { + set format {} + set arglist {} + set arglist2 {} + set i 0 + foreach col $x(*) { + lappend arglist x$i + append arglist2 " \$x$i" + incr i + append format " %-$cw($col)s" + } + set format [string trimleft $format]\n + if {[llength $arglist]>0} { + foreach $arglist $y "append res \[format [list $format] $arglist2\]" + } + } + } elseif {$mode=="multicolumn"} { + set y [$v(db) eval $cmd] + set max 0 + foreach e $y { + if {$max<[string length $e]} {set max [string length $e]} + } + set ncol [expr {int(80/($max+2))}] + if {$ncol<1} {set ncol 1} + set nelem [llength $y] + set nrow [expr {($nelem+$ncol-1)/$ncol}] + set format "%-${max}s" + for {set i 0} {$i<$nrow} {incr i} { + set j $i + while 1 { + append res [format $format [lindex $y $j]] + incr j $nrow + if {$j>=$nelem} break + append res { } + } + append res \n + } + } else { + $v(db) eval $cmd x { + foreach col $x(*) {append res "$col = $x($col)\n"} + append res \n + } + } + return [string trimright $res] +} + +# Change the line to the previous line +# +proc sqlitecon::Prior w { + upvar #0 $w v + if {$v(current)<=0} return + incr v(current) -1 + set line [lindex $v(history) $v(current)] + sqlitecon::SetLine $w $line +} + +# Change the line to the next line +# +proc sqlitecon::Next w { + upvar #0 $w v + if {$v(current)>=$v(historycnt)} return + incr v(current) 1 + set line [lindex $v(history) $v(current)] + sqlitecon::SetLine $w $line +} + +# Change the contents of the entry line +# +proc sqlitecon::SetLine {w line} { + upvar #0 $w v + scan [$w index insert] %d.%d row col + set start $row.$v(plength) + $w delete $start end + $w insert end $line + $w mark set insert end + $w yview insert +} + +# Called when the mouse button is pressed at position $x,$y on +# the console widget. +# +proc sqlitecon::Button1 {w x y} { + global tkPriv + upvar #0 $w v + set v(mouseMoved) 0 + set v(pressX) $x + set p [sqlitecon::nearestBoundry $w $x $y] + scan [$w index insert] %d.%d ix iy + scan $p %d.%d px py + if {$px==$ix} { + $w mark set insert $p + } + $w mark set anchor $p + focus $w +} + +# Find the boundry between characters that is nearest +# to $x,$y +# +proc sqlitecon::nearestBoundry {w x y} { + set p [$w index @$x,$y] + set bb [$w bbox $p] + if {![string compare $bb ""]} {return $p} + if {($x-[lindex $bb 0])<([lindex $bb 2]/2)} {return $p} + $w index "$p + 1 char" +} + +# This routine extends the selection to the point specified by $x,$y +# +proc sqlitecon::SelectTo {w x y} { + upvar #0 $w v + set cur [sqlitecon::nearestBoundry $w $x $y] + if {[catch {$w index anchor}]} { + $w mark set anchor $cur + } + set anchor [$w index anchor] + if {[$w compare $cur != $anchor] || (abs($v(pressX) - $x) >= 3)} { + if {$v(mouseMoved)==0} { + $w tag remove sel 0.0 end + } + set v(mouseMoved) 1 + } + if {[$w compare $cur < anchor]} { + set first $cur + set last anchor + } else { + set first anchor + set last $cur + } + if {$v(mouseMoved)} { + $w tag remove sel 0.0 $first + $w tag add sel $first $last + $w tag remove sel $last end + update idletasks + } +} + +# Called whenever the mouse moves while button-1 is held down. +# +proc sqlitecon::B1Motion {w x y} { + upvar #0 $w v + set v(y) $y + set v(x) $x + sqlitecon::SelectTo $w $x $y +} + +# Called whenever the mouse leaves the boundries of the widget +# while button 1 is held down. +# +proc sqlitecon::B1Leave {w x y} { + upvar #0 $w v + set v(y) $y + set v(x) $x + sqlitecon::motor $w +} + +# This routine is called to automatically scroll the window when +# the mouse drags offscreen. +# +proc sqlitecon::motor w { + upvar #0 $w v + if {![winfo exists $w]} return + if {$v(y)>=[winfo height $w]} { + $w yview scroll 1 units + } elseif {$v(y)<0} { + $w yview scroll -1 units + } else { + return + } + sqlitecon::SelectTo $w $v(x) $v(y) + set v(timer) [after 50 sqlitecon::motor $w] +} + +# This routine cancels the scrolling motor if it is active +# +proc sqlitecon::cancelMotor w { + upvar #0 $w v + catch {after cancel $v(timer)} + catch {unset v(timer)} +} + +# Do a Copy operation on the stuff currently selected. +# +proc sqlitecon::Copy w { + if {![catch {set text [$w get sel.first sel.last]}]} { + clipboard clear -displayof $w + clipboard append -displayof $w $text + } +} + +# Return 1 if the selection exists and is contained +# entirely on the input line. Return 2 if the selection +# exists but is not entirely on the input line. Return 0 +# if the selection does not exist. +# +proc sqlitecon::canCut w { + set r [catch { + scan [$w index sel.first] %d.%d s1x s1y + scan [$w index sel.last] %d.%d s2x s2y + scan [$w index insert] %d.%d ix iy + }] + if {$r==1} {return 0} + if {$s1x==$ix && $s2x==$ix} {return 1} + return 2 +} + +# Do a Cut operation if possible. Cuts are only allowed +# if the current selection is entirely contained on the +# current input line. +# +proc sqlitecon::Cut w { + if {[sqlitecon::canCut $w]==1} { + sqlitecon::Copy $w + $w delete sel.first sel.last + } +} + +# Do a paste opeation. +# +proc sqlitecon::Paste w { + if {[sqlitecon::canCut $w]==1} { + $w delete sel.first sel.last + } + if {[catch {selection get -displayof $w -selection CLIPBOARD} topaste] + && [catch {selection get -displayof $w -selection PRIMARY} topaste]} { + return + } + if {[info exists ::$w]} { + set prior 0 + foreach line [split $topaste \n] { + if {$prior} { + sqlitecon::Enter $w + update + } + set prior 1 + $w insert insert $line + } + } else { + $w insert insert $topaste + } +} + +# Enable or disable entries in the Edit menu +# +proc sqlitecon::EnableEditMenu w { + upvar #0 $w.t v + set m $v(editmenu) + if {$m=="" || ![winfo exists $m]} return + switch [sqlitecon::canCut $w.t] { + 0 { + $m entryconf Copy -state disabled + $m entryconf Cut -state disabled + } + 1 { + $m entryconf Copy -state normal + $m entryconf Cut -state normal + } + 2 { + $m entryconf Copy -state normal + $m entryconf Cut -state disabled + } + } +} + +# Prompt the user for the name of a writable file. Then write the +# entire contents of the console screen to that file. +# +proc sqlitecon::SaveFile w { + set types { + {{Text Files} {.txt}} + {{All Files} *} + } + set f [tk_getSaveFile -filetypes $types -title "Write Screen To..."] + if {$f!=""} { + if {[catch {open $f w} fd]} { + tk_messageBox -type ok -icon error -message $fd + } else { + puts $fd [string trimright [$w get 1.0 end] \n] + close $fd + } + } +} + +# Erase everything from the console above the insertion line. +# +proc sqlitecon::Clear w { + $w delete 1.0 {insert linestart} +} + +# An in-line editor for SQL +# +proc sqlitecon::_edit {origtxt {title {}}} { + for {set i 0} {[winfo exists .ed$i]} {incr i} continue + set w .ed$i + toplevel $w + wm protocol $w WM_DELETE_WINDOW "$w.b.can invoke" + wm title $w {Inline SQL Editor} + frame $w.b + pack $w.b -side bottom -fill x + button $w.b.can -text Cancel -width 6 -command [list set ::$w 0] + button $w.b.ok -text OK -width 6 -command [list set ::$w 1] + button $w.b.cut -text Cut -width 6 -command [list ::sqlitecon::Cut $w.t] + button $w.b.copy -text Copy -width 6 -command [list ::sqlitecon::Copy $w.t] + button $w.b.paste -text Paste -width 6 -command [list ::sqlitecon::Paste $w.t] + set ::$w {} + pack $w.b.cut $w.b.copy $w.b.paste $w.b.can $w.b.ok\ + -side left -padx 5 -pady 5 -expand 1 + if {$title!=""} { + label $w.title -text $title + pack $w.title -side top -padx 5 -pady 5 + } + text $w.t -bg white -fg black -yscrollcommand [list $w.sb set] + pack $w.t -side left -fill both -expand 1 + scrollbar $w.sb -orient vertical -command [list $w.t yview] + pack $w.sb -side left -fill y + $w.t insert end $origtxt + + vwait ::$w + + if {[set ::$w]} { + set txt [string trimright [$w.t get 1.0 end]] + } else { + set txt $origtxt + } + destroy $w + return $txt +} diff --git a/client/src/thirdparty/sqlite-3.4.2/doc/lemon.html b/client/src/thirdparty/sqlite-3.4.2/doc/lemon.html new file mode 100644 index 0000000..6a4d6db --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/doc/lemon.html @@ -0,0 +1,892 @@ + + +The Lemon Parser Generator + + +

The Lemon Parser Generator

+ +

Lemon is an LALR(1) parser generator for C or C++. +It does the same job as ``bison'' and ``yacc''. +But lemon is not another bison or yacc clone. It +uses a different grammar syntax which is designed to +reduce the number of coding errors. Lemon also uses a more +sophisticated parsing engine that is faster than yacc and +bison and which is both reentrant and thread-safe. +Furthermore, Lemon implements features that can be used +to eliminate resource leaks, making is suitable for use +in long-running programs such as graphical user interfaces +or embedded controllers.

+ +

This document is an introduction to the Lemon +parser generator.

+ +

Theory of Operation

+ +

The main goal of Lemon is to translate a context free grammar (CFG) +for a particular language into C code that implements a parser for +that language. +The program has two inputs: +

    +
  • The grammar specification. +
  • A parser template file. +
+Typically, only the grammar specification is supplied by the programmer. +Lemon comes with a default parser template which works fine for most +applications. But the user is free to substitute a different parser +template if desired.

+ +

Depending on command-line options, Lemon will generate between +one and three files of outputs. +

    +
  • C code to implement the parser. +
  • A header file defining an integer ID for each terminal symbol. +
  • An information file that describes the states of the generated parser + automaton. +
+By default, all three of these output files are generated. +The header file is suppressed if the ``-m'' command-line option is +used and the report file is omitted when ``-q'' is selected.

+ +

The grammar specification file uses a ``.y'' suffix, by convention. +In the examples used in this document, we'll assume the name of the +grammar file is ``gram.y''. A typical use of Lemon would be the +following command: +

+   lemon gram.y
+
+This command will generate three output files named ``gram.c'', +``gram.h'' and ``gram.out''. +The first is C code to implement the parser. The second +is the header file that defines numerical values for all +terminal symbols, and the last is the report that explains +the states used by the parser automaton.

+ +

Command Line Options

+ +

The behavior of Lemon can be modified using command-line options. +You can obtain a list of the available command-line options together +with a brief explanation of what each does by typing +

+   lemon -?
+
+As of this writing, the following command-line options are supported: +
    +
  • -b +
  • -c +
  • -g +
  • -m +
  • -q +
  • -s +
  • -x +
+The ``-b'' option reduces the amount of text in the report file by +printing only the basis of each parser state, rather than the full +configuration. +The ``-c'' option suppresses action table compression. Using -c +will make the parser a little larger and slower but it will detect +syntax errors sooner. +The ``-g'' option causes no output files to be generated at all. +Instead, the input grammar file is printed on standard output but +with all comments, actions and other extraneous text deleted. This +is a useful way to get a quick summary of a grammar. +The ``-m'' option causes the output C source file to be compatible +with the ``makeheaders'' program. +Makeheaders is a program that automatically generates header files +from C source code. When the ``-m'' option is used, the header +file is not output since the makeheaders program will take care +of generated all header files automatically. +The ``-q'' option suppresses the report file. +Using ``-s'' causes a brief summary of parser statistics to be +printed. Like this: +
+   Parser statistics: 74 terminals, 70 nonterminals, 179 rules
+                      340 states, 2026 parser table entries, 0 conflicts
+
+Finally, the ``-x'' option causes Lemon to print its version number +and then stops without attempting to read the grammar or generate a parser.

+ +

The Parser Interface

+ +

Lemon doesn't generate a complete, working program. It only generates +a few subroutines that implement a parser. This section describes +the interface to those subroutines. It is up to the programmer to +call these subroutines in an appropriate way in order to produce a +complete system.

+ +

Before a program begins using a Lemon-generated parser, the program +must first create the parser. +A new parser is created as follows: +

+   void *pParser = ParseAlloc( malloc );
+
+The ParseAlloc() routine allocates and initializes a new parser and +returns a pointer to it. +The actual data structure used to represent a parser is opaque -- +its internal structure is not visible or usable by the calling routine. +For this reason, the ParseAlloc() routine returns a pointer to void +rather than a pointer to some particular structure. +The sole argument to the ParseAlloc() routine is a pointer to the +subroutine used to allocate memory. Typically this means ``malloc()''.

+ +

After a program is finished using a parser, it can reclaim all +memory allocated by that parser by calling +

+   ParseFree(pParser, free);
+
+The first argument is the same pointer returned by ParseAlloc(). The +second argument is a pointer to the function used to release bulk +memory back to the system.

+ +

After a parser has been allocated using ParseAlloc(), the programmer +must supply the parser with a sequence of tokens (terminal symbols) to +be parsed. This is accomplished by calling the following function +once for each token: +

+   Parse(pParser, hTokenID, sTokenData, pArg);
+
+The first argument to the Parse() routine is the pointer returned by +ParseAlloc(). +The second argument is a small positive integer that tells the parse the +type of the next token in the data stream. +There is one token type for each terminal symbol in the grammar. +The gram.h file generated by Lemon contains #define statements that +map symbolic terminal symbol names into appropriate integer values. +(A value of 0 for the second argument is a special flag to the +parser to indicate that the end of input has been reached.) +The third argument is the value of the given token. By default, +the type of the third argument is integer, but the grammar will +usually redefine this type to be some kind of structure. +Typically the second argument will be a broad category of tokens +such as ``identifier'' or ``number'' and the third argument will +be the name of the identifier or the value of the number.

+ +

The Parse() function may have either three or four arguments, +depending on the grammar. If the grammar specification file request +it, the Parse() function will have a fourth parameter that can be +of any type chosen by the programmer. The parser doesn't do anything +with this argument except to pass it through to action routines. +This is a convenient mechanism for passing state information down +to the action routines without having to use global variables.

+ +

A typical use of a Lemon parser might look something like the +following: +

+   01 ParseTree *ParseFile(const char *zFilename){
+   02    Tokenizer *pTokenizer;
+   03    void *pParser;
+   04    Token sToken;
+   05    int hTokenId;
+   06    ParserState sState;
+   07
+   08    pTokenizer = TokenizerCreate(zFilename);
+   09    pParser = ParseAlloc( malloc );
+   10    InitParserState(&sState);
+   11    while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
+   12       Parse(pParser, hTokenId, sToken, &sState);
+   13    }
+   14    Parse(pParser, 0, sToken, &sState);
+   15    ParseFree(pParser, free );
+   16    TokenizerFree(pTokenizer);
+   17    return sState.treeRoot;
+   18 }
+
+This example shows a user-written routine that parses a file of +text and returns a pointer to the parse tree. +(We've omitted all error-handling from this example to keep it +simple.) +We assume the existence of some kind of tokenizer which is created +using TokenizerCreate() on line 8 and deleted by TokenizerFree() +on line 16. The GetNextToken() function on line 11 retrieves the +next token from the input file and puts its type in the +integer variable hTokenId. The sToken variable is assumed to be +some kind of structure that contains details about each token, +such as its complete text, what line it occurs on, etc.

+ +

This example also assumes the existence of structure of type +ParserState that holds state information about a particular parse. +An instance of such a structure is created on line 6 and initialized +on line 10. A pointer to this structure is passed into the Parse() +routine as the optional 4th argument. +The action routine specified by the grammar for the parser can use +the ParserState structure to hold whatever information is useful and +appropriate. In the example, we note that the treeRoot field of +the ParserState structure is left pointing to the root of the parse +tree.

+ +

The core of this example as it relates to Lemon is as follows: +

+   ParseFile(){
+      pParser = ParseAlloc( malloc );
+      while( GetNextToken(pTokenizer,&hTokenId, &sToken) ){
+         Parse(pParser, hTokenId, sToken);
+      }
+      Parse(pParser, 0, sToken);
+      ParseFree(pParser, free );
+   }
+
+Basically, what a program has to do to use a Lemon-generated parser +is first create the parser, then send it lots of tokens obtained by +tokenizing an input source. When the end of input is reached, the +Parse() routine should be called one last time with a token type +of 0. This step is necessary to inform the parser that the end of +input has been reached. Finally, we reclaim memory used by the +parser by calling ParseFree().

+ +

There is one other interface routine that should be mentioned +before we move on. +The ParseTrace() function can be used to generate debugging output +from the parser. A prototype for this routine is as follows: +

+   ParseTrace(FILE *stream, char *zPrefix);
+
+After this routine is called, a short (one-line) message is written +to the designated output stream every time the parser changes states +or calls an action routine. Each such message is prefaced using +the text given by zPrefix. This debugging output can be turned off +by calling ParseTrace() again with a first argument of NULL (0).

+ +

Differences With YACC and BISON

+ +

Programmers who have previously used the yacc or bison parser +generator will notice several important differences between yacc and/or +bison and Lemon. +

    +
  • In yacc and bison, the parser calls the tokenizer. In Lemon, + the tokenizer calls the parser. +
  • Lemon uses no global variables. Yacc and bison use global variables + to pass information between the tokenizer and parser. +
  • Lemon allows multiple parsers to be running simultaneously. Yacc + and bison do not. +
+These differences may cause some initial confusion for programmers +with prior yacc and bison experience. +But after years of experience using Lemon, I firmly +believe that the Lemon way of doing things is better.

+ +

Input File Syntax

+ +

The main purpose of the grammar specification file for Lemon is +to define the grammar for the parser. But the input file also +specifies additional information Lemon requires to do its job. +Most of the work in using Lemon is in writing an appropriate +grammar file.

+ +

The grammar file for lemon is, for the most part, free format. +It does not have sections or divisions like yacc or bison. Any +declaration can occur at any point in the file. +Lemon ignores whitespace (except where it is needed to separate +tokens) and it honors the same commenting conventions as C and C++.

+ +

Terminals and Nonterminals

+ +

A terminal symbol (token) is any string of alphanumeric +and underscore characters +that begins with an upper case letter. +A terminal can contain lower class letters after the first character, +but the usual convention is to make terminals all upper case. +A nonterminal, on the other hand, is any string of alphanumeric +and underscore characters than begins with a lower case letter. +Again, the usual convention is to make nonterminals use all lower +case letters.

+ +

In Lemon, terminal and nonterminal symbols do not need to +be declared or identified in a separate section of the grammar file. +Lemon is able to generate a list of all terminals and nonterminals +by examining the grammar rules, and it can always distinguish a +terminal from a nonterminal by checking the case of the first +character of the name.

+ +

Yacc and bison allow terminal symbols to have either alphanumeric +names or to be individual characters included in single quotes, like +this: ')' or '$'. Lemon does not allow this alternative form for +terminal symbols. With Lemon, all symbols, terminals and nonterminals, +must have alphanumeric names.

+ +

Grammar Rules

+ +

The main component of a Lemon grammar file is a sequence of grammar +rules. +Each grammar rule consists of a nonterminal symbol followed by +the special symbol ``::='' and then a list of terminals and/or nonterminals. +The rule is terminated by a period. +The list of terminals and nonterminals on the right-hand side of the +rule can be empty. +Rules can occur in any order, except that the left-hand side of the +first rule is assumed to be the start symbol for the grammar (unless +specified otherwise using the %start directive described below.) +A typical sequence of grammar rules might look something like this: +

+  expr ::= expr PLUS expr.
+  expr ::= expr TIMES expr.
+  expr ::= LPAREN expr RPAREN.
+  expr ::= VALUE.
+
+

+ +

There is one non-terminal in this example, ``expr'', and five +terminal symbols or tokens: ``PLUS'', ``TIMES'', ``LPAREN'', +``RPAREN'' and ``VALUE''.

+ +

Like yacc and bison, Lemon allows the grammar to specify a block +of C code that will be executed whenever a grammar rule is reduced +by the parser. +In Lemon, this action is specified by putting the C code (contained +within curly braces {...}) immediately after the +period that closes the rule. +For example: +

+  expr ::= expr PLUS expr.   { printf("Doing an addition...\n"); }
+
+

+ +

In order to be useful, grammar actions must normally be linked to +their associated grammar rules. +In yacc and bison, this is accomplished by embedding a ``$$'' in the +action to stand for the value of the left-hand side of the rule and +symbols ``$1'', ``$2'', and so forth to stand for the value of +the terminal or nonterminal at position 1, 2 and so forth on the +right-hand side of the rule. +This idea is very powerful, but it is also very error-prone. The +single most common source of errors in a yacc or bison grammar is +to miscount the number of symbols on the right-hand side of a grammar +rule and say ``$7'' when you really mean ``$8''.

+ +

Lemon avoids the need to count grammar symbols by assigning symbolic +names to each symbol in a grammar rule and then using those symbolic +names in the action. +In yacc or bison, one would write this: +

+  expr -> expr PLUS expr  { $$ = $1 + $3; };
+
+But in Lemon, the same rule becomes the following: +
+  expr(A) ::= expr(B) PLUS expr(C).  { A = B+C; }
+
+In the Lemon rule, any symbol in parentheses after a grammar rule +symbol becomes a place holder for that symbol in the grammar rule. +This place holder can then be used in the associated C action to +stand for the value of that symbol.

+ +

The Lemon notation for linking a grammar rule with its reduce +action is superior to yacc/bison on several counts. +First, as mentioned above, the Lemon method avoids the need to +count grammar symbols. +Secondly, if a terminal or nonterminal in a Lemon grammar rule +includes a linking symbol in parentheses but that linking symbol +is not actually used in the reduce action, then an error message +is generated. +For example, the rule +

+  expr(A) ::= expr(B) PLUS expr(C).  { A = B; }
+
+will generate an error because the linking symbol ``C'' is used +in the grammar rule but not in the reduce action.

+ +

The Lemon notation for linking grammar rules to reduce actions +also facilitates the use of destructors for reclaiming memory +allocated by the values of terminals and nonterminals on the +right-hand side of a rule.

+ +

Precedence Rules

+ +

Lemon resolves parsing ambiguities in exactly the same way as +yacc and bison. A shift-reduce conflict is resolved in favor +of the shift, and a reduce-reduce conflict is resolved by reducing +whichever rule comes first in the grammar file.

+ +

Just like in +yacc and bison, Lemon allows a measure of control +over the resolution of paring conflicts using precedence rules. +A precedence value can be assigned to any terminal symbol +using the %left, %right or %nonassoc directives. Terminal symbols +mentioned in earlier directives have a lower precedence that +terminal symbols mentioned in later directives. For example:

+ +

+   %left AND.
+   %left OR.
+   %nonassoc EQ NE GT GE LT LE.
+   %left PLUS MINUS.
+   %left TIMES DIVIDE MOD.
+   %right EXP NOT.
+

+ +

In the preceding sequence of directives, the AND operator is +defined to have the lowest precedence. The OR operator is one +precedence level higher. And so forth. Hence, the grammar would +attempt to group the ambiguous expression +

+     a AND b OR c
+
+like this +
+     a AND (b OR c).
+
+The associativity (left, right or nonassoc) is used to determine +the grouping when the precedence is the same. AND is left-associative +in our example, so +
+     a AND b AND c
+
+is parsed like this +
+     (a AND b) AND c.
+
+The EXP operator is right-associative, though, so +
+     a EXP b EXP c
+
+is parsed like this +
+     a EXP (b EXP c).
+
+The nonassoc precedence is used for non-associative operators. +So +
+     a EQ b EQ c
+
+is an error.

+ +

The precedence of non-terminals is transferred to rules as follows: +The precedence of a grammar rule is equal to the precedence of the +left-most terminal symbol in the rule for which a precedence is +defined. This is normally what you want, but in those cases where +you want to precedence of a grammar rule to be something different, +you can specify an alternative precedence symbol by putting the +symbol in square braces after the period at the end of the rule and +before any C-code. For example:

+ +

+   expr = MINUS expr.  [NOT]
+

+ +

This rule has a precedence equal to that of the NOT symbol, not the +MINUS symbol as would have been the case by default.

+ +

With the knowledge of how precedence is assigned to terminal +symbols and individual +grammar rules, we can now explain precisely how parsing conflicts +are resolved in Lemon. Shift-reduce conflicts are resolved +as follows: +

    +
  • If either the token to be shifted or the rule to be reduced + lacks precedence information, then resolve in favor of the + shift, but report a parsing conflict. +
  • If the precedence of the token to be shifted is greater than + the precedence of the rule to reduce, then resolve in favor + of the shift. No parsing conflict is reported. +
  • If the precedence of the token it be shifted is less than the + precedence of the rule to reduce, then resolve in favor of the + reduce action. No parsing conflict is reported. +
  • If the precedences are the same and the shift token is + right-associative, then resolve in favor of the shift. + No parsing conflict is reported. +
  • If the precedences are the same the the shift token is + left-associative, then resolve in favor of the reduce. + No parsing conflict is reported. +
  • Otherwise, resolve the conflict by doing the shift and + report the parsing conflict. +
+Reduce-reduce conflicts are resolved this way: +
    +
  • If either reduce rule + lacks precedence information, then resolve in favor of the + rule that appears first in the grammar and report a parsing + conflict. +
  • If both rules have precedence and the precedence is different + then resolve the dispute in favor of the rule with the highest + precedence and do not report a conflict. +
  • Otherwise, resolve the conflict by reducing by the rule that + appears first in the grammar and report a parsing conflict. +
+ +

Special Directives

+ +

The input grammar to Lemon consists of grammar rules and special +directives. We've described all the grammar rules, so now we'll +talk about the special directives.

+ +

Directives in lemon can occur in any order. You can put them before +the grammar rules, or after the grammar rules, or in the mist of the +grammar rules. It doesn't matter. The relative order of +directives used to assign precedence to terminals is important, but +other than that, the order of directives in Lemon is arbitrary.

+ +

Lemon supports the following special directives: +

    +
  • %code +
  • %default_destructor +
  • %default_type +
  • %destructor +
  • %extra_argument +
  • %include +
  • %left +
  • %name +
  • %nonassoc +
  • %parse_accept +
  • %parse_failure +
  • %right +
  • %stack_overflow +
  • %stack_size +
  • %start_symbol +
  • %syntax_error +
  • %token_destructor +
  • %token_prefix +
  • %token_type +
  • %type +
+Each of these directives will be described separately in the +following sections:

+ +

The %code directive

+ +

The %code directive is used to specify addition C/C++ code that +is added to the end of the main output file. This is similar to +the %include directive except that %include is inserted at the +beginning of the main output file.

+ +

%code is typically used to include some action routines or perhaps +a tokenizer as part of the output file.

+ +

The %default_destructor directive

+ +

The %default_destructor directive specifies a destructor to +use for non-terminals that do not have their own destructor +specified by a separate %destructor directive. See the documentation +on the %destructor directive below for additional information.

+ +

In some grammers, many different non-terminal symbols have the +same datatype and hence the same destructor. This directive is +a convenience way to specify the same destructor for all those +non-terminals using a single statement.

+ +

The %default_type directive

+ +

The %default_type directive specifies the datatype of non-terminal +symbols that do no have their own datatype defined using a separate +%type directive. See the documentation on %type below for addition +information.

+ +

The %destructor directive

+ +

The %destructor directive is used to specify a destructor for +a non-terminal symbol. +(See also the %token_destructor directive which is used to +specify a destructor for terminal symbols.)

+ +

A non-terminal's destructor is called to dispose of the +non-terminal's value whenever the non-terminal is popped from +the stack. This includes all of the following circumstances: +

    +
  • When a rule reduces and the value of a non-terminal on + the right-hand side is not linked to C code. +
  • When the stack is popped during error processing. +
  • When the ParseFree() function runs. +
+The destructor can do whatever it wants with the value of +the non-terminal, but its design is to deallocate memory +or other resources held by that non-terminal.

+ +

Consider an example: +

+   %type nt {void*}
+   %destructor nt { free($$); }
+   nt(A) ::= ID NUM.   { A = malloc( 100 ); }
+
+This example is a bit contrived but it serves to illustrate how +destructors work. The example shows a non-terminal named +``nt'' that holds values of type ``void*''. When the rule for +an ``nt'' reduces, it sets the value of the non-terminal to +space obtained from malloc(). Later, when the nt non-terminal +is popped from the stack, the destructor will fire and call +free() on this malloced space, thus avoiding a memory leak. +(Note that the symbol ``$$'' in the destructor code is replaced +by the value of the non-terminal.)

+ +

It is important to note that the value of a non-terminal is passed +to the destructor whenever the non-terminal is removed from the +stack, unless the non-terminal is used in a C-code action. If +the non-terminal is used by C-code, then it is assumed that the +C-code will take care of destroying it if it should really +be destroyed. More commonly, the value is used to build some +larger structure and we don't want to destroy it, which is why +the destructor is not called in this circumstance.

+ +

By appropriate use of destructors, it is possible to +build a parser using Lemon that can be used within a long-running +program, such as a GUI, that will not leak memory or other resources. +To do the same using yacc or bison is much more difficult.

+ +

The %extra_argument directive

+ +The %extra_argument directive instructs Lemon to add a 4th parameter +to the parameter list of the Parse() function it generates. Lemon +doesn't do anything itself with this extra argument, but it does +make the argument available to C-code action routines, destructors, +and so forth. For example, if the grammar file contains:

+ +

+    %extra_argument { MyStruct *pAbc }
+

+ +

Then the Parse() function generated will have an 4th parameter +of type ``MyStruct*'' and all action routines will have access to +a variable named ``pAbc'' that is the value of the 4th parameter +in the most recent call to Parse().

+ +

The %include directive

+ +

The %include directive specifies C code that is included at the +top of the generated parser. You can include any text you want -- +the Lemon parser generator copies it blindly. If you have multiple +%include directives in your grammar file the value of the last +%include directive overwrites all the others.The %include directive is very handy for getting some extra #include +preprocessor statements at the beginning of the generated parser. +For example:

+ +

+   %include {#include <unistd.h>}
+

+ +

This might be needed, for example, if some of the C actions in the +grammar call functions that are prototyed in unistd.h.

+ +

The %left directive

+ +The %left directive is used (along with the %right and +%nonassoc directives) to declare precedences of terminal +symbols. Every terminal symbol whose name appears after +a %left directive but before the next period (``.'') is +given the same left-associative precedence value. Subsequent +%left directives have higher precedence. For example:

+ +

+   %left AND.
+   %left OR.
+   %nonassoc EQ NE GT GE LT LE.
+   %left PLUS MINUS.
+   %left TIMES DIVIDE MOD.
+   %right EXP NOT.
+

+ +

Note the period that terminates each %left, %right or %nonassoc +directive.

+ +

LALR(1) grammars can get into a situation where they require +a large amount of stack space if you make heavy use or right-associative +operators. For this reason, it is recommended that you use %left +rather than %right whenever possible.

+ +

The %name directive

+ +

By default, the functions generated by Lemon all begin with the +five-character string ``Parse''. You can change this string to something +different using the %name directive. For instance:

+ +

+   %name Abcde
+

+ +

Putting this directive in the grammar file will cause Lemon to generate +functions named +

    +
  • AbcdeAlloc(), +
  • AbcdeFree(), +
  • AbcdeTrace(), and +
  • Abcde(). +
+The %name directive allows you to generator two or more different +parsers and link them all into the same executable. +

+ +

The %nonassoc directive

+ +

This directive is used to assign non-associative precedence to +one or more terminal symbols. See the section on precedence rules +or on the %left directive for additional information.

+ +

The %parse_accept directive

+ +

The %parse_accept directive specifies a block of C code that is +executed whenever the parser accepts its input string. To ``accept'' +an input string means that the parser was able to process all tokens +without error.

+ +

For example:

+ +

+   %parse_accept {
+      printf("parsing complete!\n");
+   }
+

+ + +

The %parse_failure directive

+ +

The %parse_failure directive specifies a block of C code that +is executed whenever the parser fails complete. This code is not +executed until the parser has tried and failed to resolve an input +error using is usual error recovery strategy. The routine is +only invoked when parsing is unable to continue.

+ +

+   %parse_failure {
+     fprintf(stderr,"Giving up.  Parser is hopelessly lost...\n");
+   }
+

+ +

The %right directive

+ +

This directive is used to assign right-associative precedence to +one or more terminal symbols. See the section on precedence rules +or on the %left directive for additional information.

+ +

The %stack_overflow directive

+ +

The %stack_overflow directive specifies a block of C code that +is executed if the parser's internal stack ever overflows. Typically +this just prints an error message. After a stack overflow, the parser +will be unable to continue and must be reset.

+ +

+   %stack_overflow {
+     fprintf(stderr,"Giving up.  Parser stack overflow\n");
+   }
+

+ +

You can help prevent parser stack overflows by avoiding the use +of right recursion and right-precedence operators in your grammar. +Use left recursion and and left-precedence operators instead, to +encourage rules to reduce sooner and keep the stack size down. +For example, do rules like this: +

+   list ::= list element.      // left-recursion.  Good!
+   list ::= .
+
+Not like this: +
+   list ::= element list.      // right-recursion.  Bad!
+   list ::= .
+
+ +

The %stack_size directive

+ +

If stack overflow is a problem and you can't resolve the trouble +by using left-recursion, then you might want to increase the size +of the parser's stack using this directive. Put an positive integer +after the %stack_size directive and Lemon will generate a parse +with a stack of the requested size. The default value is 100.

+ +

+   %stack_size 2000
+

+ +

The %start_symbol directive

+ +

By default, the start-symbol for the grammar that Lemon generates +is the first non-terminal that appears in the grammar file. But you +can choose a different start-symbol using the %start_symbol directive.

+ +

+   %start_symbol  prog
+

+ +

The %token_destructor directive

+ +

The %destructor directive assigns a destructor to a non-terminal +symbol. (See the description of the %destructor directive above.) +This directive does the same thing for all terminal symbols.

+ +

Unlike non-terminal symbols which may each have a different data type +for their values, terminals all use the same data type (defined by +the %token_type directive) and so they use a common destructor. Other +than that, the token destructor works just like the non-terminal +destructors.

+ +

The %token_prefix directive

+ +

Lemon generates #defines that assign small integer constants +to each terminal symbol in the grammar. If desired, Lemon will +add a prefix specified by this directive +to each of the #defines it generates. +So if the default output of Lemon looked like this: +

+    #define AND              1
+    #define MINUS            2
+    #define OR               3
+    #define PLUS             4
+
+You can insert a statement into the grammar like this: +
+    %token_prefix    TOKEN_
+
+to cause Lemon to produce these symbols instead: +
+    #define TOKEN_AND        1
+    #define TOKEN_MINUS      2
+    #define TOKEN_OR         3
+    #define TOKEN_PLUS       4
+
+ +

The %token_type and %type directives

+ +

These directives are used to specify the data types for values +on the parser's stack associated with terminal and non-terminal +symbols. The values of all terminal symbols must be of the same +type. This turns out to be the same data type as the 3rd parameter +to the Parse() function generated by Lemon. Typically, you will +make the value of a terminal symbol by a pointer to some kind of +token structure. Like this:

+ +

+   %token_type    {Token*}
+

+ +

If the data type of terminals is not specified, the default value +is ``int''.

+ +

Non-terminal symbols can each have their own data types. Typically +the data type of a non-terminal is a pointer to the root of a parse-tree +structure that contains all information about that non-terminal. +For example:

+ +

+   %type   expr  {Expr*}
+

+ +

Each entry on the parser's stack is actually a union containing +instances of all data types for every non-terminal and terminal symbol. +Lemon will automatically use the correct element of this union depending +on what the corresponding non-terminal or terminal symbol is. But +the grammar designer should keep in mind that the size of the union +will be the size of its largest element. So if you have a single +non-terminal whose data type requires 1K of storage, then your 100 +entry parser stack will require 100K of heap space. If you are willing +and able to pay that price, fine. You just need to know.

+ +

Error Processing

+ +

After extensive experimentation over several years, it has been +discovered that the error recovery strategy used by yacc is about +as good as it gets. And so that is what Lemon uses.

+ +

When a Lemon-generated parser encounters a syntax error, it +first invokes the code specified by the %syntax_error directive, if +any. It then enters its error recovery strategy. The error recovery +strategy is to begin popping the parsers stack until it enters a +state where it is permitted to shift a special non-terminal symbol +named ``error''. It then shifts this non-terminal and continues +parsing. But the %syntax_error routine will not be called again +until at least three new tokens have been successfully shifted.

+ +

If the parser pops its stack until the stack is empty, and it still +is unable to shift the error symbol, then the %parse_failed routine +is invoked and the parser resets itself to its start state, ready +to begin parsing a new file. This is what will happen at the very +first syntax error, of course, if there are no instances of the +``error'' non-terminal in your grammar.

+ + + diff --git a/client/src/thirdparty/sqlite-3.4.2/doc/report1.txt b/client/src/thirdparty/sqlite-3.4.2/doc/report1.txt new file mode 100644 index 0000000..a236e7c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/doc/report1.txt @@ -0,0 +1,121 @@ +An SQLite (version 1.0) database was used in a large military application +where the database contained 105 tables and indices. The following is +a breakdown on the sizes of keys and data within these tables and indices: + +Entries: 967089 +Size: 45896104 +Avg Size: 48 +Key Size: 11112265 +Avg Key Size: 12 +Max Key Size: 99 + + 0..8 263 0% + 9..12 5560 0% + 13..16 71394 7% + 17..24 180717 26% + 25..32 215442 48% + 33..40 151118 64% + 41..48 77479 72% + 49..56 13983 74% + 57..64 14481 75% + 65..80 41342 79% + 81..96 127098 92% + 97..112 38054 96% + 113..128 14197 98% + 129..144 8208 99% + 145..160 3326 99% + 161..176 1242 99% + 177..192 604 99% + 193..208 222 99% + 209..224 213 99% + 225..240 132 99% + 241..256 58 99% + 257..288 515 99% + 289..320 64 99% + 321..352 39 99% + 353..384 44 99% + 385..416 25 99% + 417..448 24 99% + 449..480 26 99% + 481..512 27 99% + 513..1024 470 99% + 1025..2048 396 99% + 2049..4096 187 99% + 4097..8192 78 99% + 8193..16384 35 99% +16385..32768 17 99% +32769..65536 6 99% +65537..65541 3 100% + +If the indices are omitted, the statistics for the 49 tables +become the following: + +Entries: 451103 +Size: 30930282 +Avg Size: 69 +Key Size: 1804412 +Avg Key Size: 4 +Max Key Size: 4 + + 0..24 89 0% + 25..32 9417 2% + 33..40 119162 28% + 41..48 68710 43% + 49..56 9539 45% + 57..64 12435 48% + 65..80 38650 57% + 81..96 126877 85% + 97..112 38030 93% + 113..128 14183 96% + 129..144 7668 98% + 145..160 3302 99% + 161..176 1238 99% + 177..192 597 99% + 193..208 217 99% + 209..224 211 99% + 225..240 130 99% + 241..256 57 99% + 257..288 100 99% + 289..320 62 99% + 321..352 34 99% + 353..384 43 99% + 385..416 24 99% + 417..448 24 99% + 449..480 25 99% + 481..512 27 99% + 513..1024 153 99% + 1025..2048 92 99% + 2049..4096 7 100% + +The 56 indices have these statistics: + +Entries: 512422 +Size: 14879828 +Avg Size: 30 +Key Size: 9253204 +Avg Key Size: 19 +Max Key Size: 99 + + 0..8 246 0% + 9..12 5486 1% + 13..16 70717 14% + 17..24 178246 49% + 25..32 205722 89% + 33..40 31951 96% + 41..48 8768 97% + 49..56 4444 98% + 57..64 2046 99% + 65..80 2691 99% + 81..96 202 99% + 97..112 11 99% + 113..144 527 99% + 145..160 20 99% + 161..288 406 99% + 289..1024 316 99% + 1025..2048 304 99% + 2049..4096 180 99% + 4097..8192 78 99% + 8193..16384 35 99% +16385..32768 17 99% +32769..65536 6 99% +65537..65541 3 100% diff --git a/client/src/thirdparty/sqlite-3.4.2/ex1 b/client/src/thirdparty/sqlite-3.4.2/ex1 new file mode 100644 index 0000000000000000000000000000000000000000..c952bee528e3274722b652b987bef22b9095d15b GIT binary patch literal 2048 zcmWFz^vNtqRY=P(%1ta$FlJz3U}R))P*7lCU| zAQ}auAut*OR0#nWMmBL#QO4Yo#H5_mlB66%5N2`?a&-)GRS0o(@^MuFiD=~Kr7Dyq z7A0pS7HJq7XzD1Gl;*;AUc$W=zk| VPf4mw72#xL7H7;z&B@8<0svdrB)b3r literal 0 HcmV?d00001 diff --git a/client/src/thirdparty/sqlite-3.4.2/examples/c1.bat b/client/src/thirdparty/sqlite-3.4.2/examples/c1.bat new file mode 100644 index 0000000..a95e307 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/examples/c1.bat @@ -0,0 +1,4 @@ +cls +gpp example1.cpp libsqlite3.a -o example1.exe +pause +example1.exe diff --git a/client/src/thirdparty/sqlite-3.4.2/examples/c2.bat b/client/src/thirdparty/sqlite-3.4.2/examples/c2.bat new file mode 100644 index 0000000..fd228c4 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/examples/c2.bat @@ -0,0 +1,4 @@ +cls +gpp example2.cpp libsqlite3.a -o example2.exe +pause +example2.exe diff --git a/client/src/thirdparty/sqlite-3.4.2/examples/c3.bat b/client/src/thirdparty/sqlite-3.4.2/examples/c3.bat new file mode 100644 index 0000000..394a863 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/examples/c3.bat @@ -0,0 +1,4 @@ +cls +gcc example3.c libsqlite3.a -o example3.exe +pause +example3.exe diff --git a/client/src/thirdparty/sqlite-3.4.2/examples/example1.cpp b/client/src/thirdparty/sqlite-3.4.2/examples/example1.cpp new file mode 100644 index 0000000..691b597 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/examples/example1.cpp @@ -0,0 +1,36 @@ +#include +#include +#include "sqlite3.h" + +sqlite3 *database; + +using namespace std; + +int Callback( void *Pointer, int argc, char **argv, char **columnNames) +// (pointer to database,number of columns retrieved, +// array of pointers to the strings in the fields,column name) +{ + cout<< *argv < +#include "sqlite3.h" + +// This is the callback function to display the select data in the table +static int callback(void *NotUsed, int argc, char **argv, char **azColName) +{ + int i; + for(i=0; i +#include +#include "sqlite3.h" + + +int main(void) { + sqlite3 *db; + sqlite3_stmt *res; + int rc = 0; + int rec_count = 0; + const char *errMSG; + const char *tail; + + + rc = sqlite3_open("ex3.db", &db); + if (rc) { + puts("Can not open database"); + exit(0); + } + + // Create a new table called people in database + rc = sqlite3_exec(db,"create table people (id integer, firstname varchar(20), \ + lastname varchar(20), phonenumber char(10))", 0, 0, 0); + + //rc = sqlite3_exec(db,"delete from people", 0, 0, 0); //erase previous inserts + + rc = sqlite3_exec(db,"insert into people (id, firstname, lastname, phonenumber) \ + values (1, 'Fred', 'Flintstone', '5055551234');", NULL , NULL , NULL); + + rc = sqlite3_exec(db,"insert into people (id, firstname, lastname, phonenumber) \ + values (2, 'Wilma', 'Flintstone', '5055551234');" , NULL , NULL , NULL); + + rc = sqlite3_exec(db,"insert into people (id, firstname, lastname, phonenumber) \ + values (3, 'Barny', 'Rubble', '5055554321');" , NULL , NULL , NULL); + + rc = sqlite3_exec(db,"update people set phonenumber=\'5055559999\' where id=3", 0, 0, 0); + + rc = sqlite3_prepare_v2(db,"select lastname,firstname,phonenumber,id from people order by id", + 1000, &res, &tail); + + if (rc != SQLITE_OK) { + puts("We did not get any data!"); + exit(0); + } + puts("=========================="); + + while (sqlite3_step(res) == SQLITE_ROW) { + printf("%s|", sqlite3_column_text(res, 0)); + printf("%s|", sqlite3_column_text(res, 1)); + printf("%s|", sqlite3_column_text(res, 2)); + printf("%u\n", sqlite3_column_int(res, 3)); + + rec_count++; + } + + puts("=========================="); + printf("We received %d records.\n", rec_count); + + sqlite3_finalize(res); + + sqlite3_close(db); + + return 0; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/examples/libsqlite3.a b/client/src/thirdparty/sqlite-3.4.2/examples/libsqlite3.a new file mode 100644 index 0000000000000000000000000000000000000000..958880909454f56a008ebf25cc49ab670d4825d4 GIT binary patch literal 1839418 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%0ANM%VsYc`fla3*g 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

`( zUxF@&+uf~$o6IV8qwDI%aSh5n%hh#1atq%Jx7@ScUnnNzlyRz?VYxls=M)KfWprsN zt0(syLqcAe5NVu=rdkK!T=#v&%3RV^T^$QqFSlbylTF4|YoEeyUqxaTsYWe|2h-i& z?r25JB5lU1WhirQiJ}Z4#gvtFccr2YLs`MC8nw&t%m)jg@jM4vu{si|v)sP!O^PuO zSvqcw&F$wtq3Gj~B%ea)USK(boy?N1Q+_A3otXliDYCe9qygBOAYR}qXf!_s6vuC} z%WuS-Qqkr#>dcA-_Focn3g;C2KGVmFiK#?!#h73}1VUGv5~`o{2o0)SeRGNHb>(SC z)m7!w?`~pO2AogdvXyo_cBP!rSG5u^puQ|LpKcLnxQ~Sj(LqMnEp`Kq`^S*BZ?T1w zi)q|vLVs7@1cEh})t5!;aTMQu*06fP5~1x6y{Gt+=nb^GpKIG8N;XJ8=97(i{rj(jKV>j z|F2wzR-tTcZ37y^*Fq{?((y_yXI|Y%Xg;FckvQO<*_Cg(p<93@E>sO&r=knMwkvTW zS<6G$k(Id6T^8yDLtPiu7|+;n)kjndR2!P1?4spDplWzSfm?5AXuQTCRQf&^w<*-9 zIMION{o_)fd3oqZiX2MV#A<4V(MpxHGW38lN0nqMfK{P=ih>#m)gc-cG<%`{DiUg> zX}s;oz1r}gD$1`#=2&C&XsFPA!87WXyEc@rdeW$YbSK|k7aFN3sDE@1({k5`N)-te z&=|bj1Z&rr0HXTQP3{ImK*eLmF>bRVq2}@Xx0bun5XUjtHD&Bq@!==S-4yzr@}q!_ zzphDJLI)ISim72PLF_uKKdKa~Y9xm=_T4&fLPke9oT>hf0VSEm+zT*Oy#Nc97hodl z+Ny?DXw;bqMl4odV6HGQJro0|tA+XtpW2xSM!dWcmXTAuz!qU+(sZT~sDBXZzkI50 zvQ@RJB0&RivV-jfo<$|#1^y(q&VdY+Tb&i61(+XETrSLXe3)jM%QVIph!N9HM^!xQ zY?#Ig(+%yJRM-@a11

B)(Y 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

Ac~^$(!vD=iwaB2N~af;Ei5RQJFjeRc~Mc} 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𝔘gYEw zf8 zfLL{4ntQ1h;vIC2-aOo*2McG^R;SwWwq$wPiGx`V_m&!}&hL2@xIx&D2E8WBD~Aj9YzB<(Tm*C>AO7bI5_+)7rCA9W8Ffl5s_>V&EEo|iu;baJFXZX{2(%>o;1g=P-cXG(#@{qIh~_nud$nX$@~ zfblr5PI|uP5Cww)NkxY0PhLwsg2O$#cq#393{wRlR2ZV_4Od`z+N$7Hy0lhe9mO1* zFh}UmGOpn);O5fyqB&BRTO6Zc`83rdY@nH=6eh@)x~v8OM(Zzey?C4@z~LhEYE@tY z&Kpqr8ifP0eKiB(bZK{_IBJ(MV2rAPGctU(#vH2vQ^5QXNai?|o`Hi7l#W*@XQNwC zn0(&EOi+b#q&t>{Z3XjM1)J}{E-LIBbG+W0J6q%ckJ7!|IFV4YY(5+?GZ2a?{YBQ4 zvO1jKFt1aHDu0ownb+$F8DF)d4*O3NRjE1$w6i%$r5YVgHC4AZ@xdH3Q3jrHDh9@W zZT(~!2RD;c+1tt6#^$Q@xXok+^KqE^vc{(R8t$%Urs#*!ET4ywaMjIJRo;h#9k4L_VzK9ri7>=jZ<=Gf}M)mrfNB%24;%|uu;cp?|Wdcn{Ro<#ezI82JZ zBvPY;JoK1ETbKjoo@8(`1r7!sC3p&PH$G#F$5c|cgAURl(zXE#kwz!sER(!o%On|Q znG|cpP9;B+dlXGV4sys9d<`A8bJf2H+m*c*|BdEX8c2^V_A->DTpg${8h_a1fw)t?8b0b{eQk?vF}E@ z#d~KoeOwd;uHyo92JXKL(BT;rC_t8MoldR&U)$ma)j(FF&;T0nOL$<7h*Rh~x$eAQ z1ca0^U>0zbHNz#S8H(@8W+=LPSu;IncvOczMm5W%c&^0`zGag4XPIPuSsVqjO!8Ah zN#xBbuG1`I28UK0RWejFQ(3++`cOhMW+|JQwi@U!ypaa_L&G>&mn zFw!#bpB(+GSuD6VW9V+{DnO zAAFMngg8oTYv8xutkPsktw+l$q9a?hjCu~{NXM)}H2_AYU5&;-UBRgKH} zaPfMRm?_{WN>p*ieI}Wpj@1;WT3XzIwtp2sDDmIlJ%H7dtE-A(wLYLA2(7{*)r?=O zIAxf$;~!LEOpeRf*3sq$$%cp2kX(*i5CN4N4cis0kE1FOliZ>DPyRTp=ACLbVf`*> zV26DdcNoW5V0u)On9+=f&2b#t8jdkj3~xX>k`xN)rdx_%3?QB-1CyZ!%03A}WSQjq z3~?IeK|5$7V3-;eL4n8)%f`wc$3>lS)r_hjX|!2n+8DQ}5{RLYe3dc3WkCyoP_SM4 zAQ(wx)`CmSk;FLBYPfagq#!6eoR3lFWFjRYhF#RMnIxsW*=IKB*Gwi21o_L`kn)^@ znId60B~(^lONK=1AJHg|2f6BNS5}qIY$!nN5a2Wk?(ZsYoW?t!X1at7a3S&{50NR9 z88YKaR}HpV0E59JAu&A-E3BC^W1y?9p{%L27Sw={o|z?~gIuL5ggd8pMOh=P%_%Zt zFb)W*qEjU#77!UEFsDh#5ZBV$iY5SMD9xNM)#6asa>g}ZdWhx>IsD-++M_XN$}O5W zR}HU#IZIAoyi1<-Gqa@&H^Eg!u>*6qtUSqu0EKF1jtmNB^dZe}&Lz!n44cx2qIBjw ziEW0fq3qTy-d;9yB!=02=v4}Klk8tL$aW?Z?>vx%2oTTWKVj`-EOQl| z>w=|ZuBQGCtfP3hc^e5osdeTeo0(v+77dGwC(APTk=f;vCfI(tYpwCgF**ZjzAAV4 z;OkNCEddOg))!4^rtd*OuAs+$rvCyVs>!de#hUzG4iN+`5Am8`Nr369;$yz%*D`JO zp%a_tKd3J4#}~`$-~5}?P7IjZ96$pimql^5kZ#O{{s2YubC`K?Arh{dsW_jDMgB3+ zex0KGOR@#iB|`z`Pcm)M)+M_@ni;HD0R{F>WxAhfv0urrM3^D!%?C{y+`W{QgiS!% zmr&(Wg`vxTz?KPaC?JU+f@4VEaseO4ozORg~e-_{&Xz@Ax{VUqK zTDBF&4pM()TtmCCdT*UOC$h!kSTk(Sz zp)d$de~)DMTL6q8Wq~yHn%+nrL9$XNzejRRT~@QEA0sq+jy9I2cniR9;>T%d+FYO; z_Y(n;KtswdmZm$|>)0N}dj@sbJi>gw$;*2bb-%&SGpO<#)K5^Bz5XUsSG$(LDmIWb zwQB=t7xP3e#x&D9$uo}nH9BMc78v^g;}`h31gzuhAXYWx(h(@5U7NrwA19srcD$(- zK#F2bWjMiHy{cz5uGjTg;GwVV4HBBR@Vah%69f3J=f#*L&G>e6Jg-HfN?JXArm2|P zOhogo?C4P-oI4lSk>hU`mU28+<2xCvY1byg)7Q`OfPRhqNp(TZ=h(vAD9h8Xb8sicTy`xQs?<`eRXF z60EVdcJWe#KK0*6y)==UtgmXUTwaFv0T$PDd|`1_184=O8}wD?`qcmK6t|-3uSZ41 zBCEEJ%x-MIEv7e1^zVarh2kYU(6lxSxD)9?*P_Ue&4e#9v5rGnx*kP>U&DM(t(N*ghLrxYlPsx^IhS(o$4`gq;f;K5^GCwOgS#o51{Vgin|pk7IF0=p zBu6e(H7Bwus_7-+v}kF_!XiA2?tY_C{)1<{0U3!{Ku!N9f})7Ks9^eza1aX7a1t88 z1Wo4VUqBu=m&wg_P*v_t7Wd|Tq(|;iHRYVo;Ce>;e6)QSZ9hl&RzTFOWZV5BAzT4L zBa?A(p3~FO>}>qpg`%lApk7@|Z#wE5gYqE*9fB@#*G4u@hNi+#D&E5glxPhq;u7@5 zE;RQonmaho$?zq81|y$^8AmI~qOPcraLE=+>`>SSbN4k~!n z2gBv(IjCeJxfV&{w5r~U)3lT#)G1eW?&a~{5U8`2=WP{|Y0W4l=jef+IZEFK3H=3r z?osvIEuz^+xIU4{Jr1Xd)Zv`ZJ;Av4(R*F6Dl7^TiZ70n@nPaAaTtAP%N;3lou+EzIB+mT-Qy zrq2u|!SDnn^E7=Hi=q#ZN;}X!^o4<@X$lv03#--SDCjqYl7yH7A95m};?!^C(p~~o zVHF)wJ=rYHBmKZy*8taLy9S zAt`wUkLqb8)A~WP$~hXqWtfiBW1+?J@iRhUZtO*C^eHN6=>&fnKV_6xS5Z@|>5

xpCL^FWMNW(kb+~k!^{!%2x@blYLiw%>3L8zonMY+^w@a3Q& z3apCuGiy_uq3;99U2C-s04vW{Br(Hp1J5`3c>z5ke4Cgn zpW(7tJ)61mbt;?kgn;>+f!WKY*^3G$ugz$`aUx>8dUP=L?ig2t{Bd#e%K(->!6Z)q zHXKc0rvlRFieREe`znl<1zz7^Vx~JsP@ma})cXaK&v-W`Z(_iW)cZ4RKDZ!}d|7<} zci~H`W_t=^C2r;)^P>Lp5XTu9Rga;v8a0&kLRgF(T>Q)O3UwHhdzrVkF5>vd{P zdMbok1%5ix$sR0TRb5+LN^eCXJg-j)Ch?@DjlxV%TuldY^~zxKYG>eQ;_9h2r87#Q zaH|-04`8Xa^5lemi<-6~@EFSEuh#Ts+|e(nRPhSD|E}rP43T2K4ozfX)+Kc(g%EX{ zacDgKE{N2__*qQ381P%nRAVSFWeaM(uHerwLuCNY4Ecv%v>5qFrX58o$&kCb3<)h9 z?bT)Kb}Hh;Iw?W6rxy+S?}Q&Mj6z1zWZCiNvc}?#Y`y<~5P|pNL%usG`B9{k%01fBh@rY{p}# z%)}IoX7lh)O4Z5yM?GTE&~-G7T|j!(REcOL+g=HP z^RkU%`)nSPa@j_+UAr9VkzU|?8$XkzEt0?$CrL}?TDhkMCIIT=gj$9^b(?*oUom>N zX*M(9&jgUh)}8E9buj=8#?Dys^{P8}h0y}dMKaxh$e)9s{e*orae4>8W43|HuAaXX zLb#Iw_YnXm3G~B^>vbfxw9_(5R?#Os z^uwI~l90-;eduq7Q$#2d4(!MZ)cg!TQh1%@qEnH9{(8|@+Izc!vo*b#<#iDl^f3G)^?Y>ip#YlJ(<4fg13%KW?>=Cv?X%N`mFNQhD!g3UOm0a!$PEY4_ zmOTHj_hnceU|P!ks6QU{C68`l9z9Gs=>s9xH{j=X!cInqpBefKM%BQ9S^mg@{&y$2 zAtnr~k=3fsB*?(;oxHUPuMJH+4kTD5?qVr7Ps)$|#xm9keHi!R5QF$YnLeB$z2Kin1M4bARzv>E>YgCo2#d7wuc*{s%#l8l zOZll3WXUK_CBy1YT}_8xG<~#1k$j3Uq>aM#NLy_p7h8>DSlPRf9|YD+#LUTc|1&F` zN0Ci9-(r3A5*1FTa$n%*A)006on`*}8<%96@CAzi9|1@zf5}Wg9OmuFdr|Fm{7hno z?_&N|%&zq&+L(w^So93^@*trH`GzymuO{mlLPDklEJ7`<5~ZX)a2+eLVn9<40QhfJ zHIWZnyaX^+m8r2ARP|ewN(J&Fe&t@jk@Ds9apb4PQdg>wU&a`&XJZFN$~n0fN%}W{ zw&2K#=g_;Qg;7wGe_1BId&u*`g_;9}?$XA{m~T&H@r|v>bcmd}s8ESVZ3(Ix97osn zpTc`<_=+3^1%hyz{5F-QQLJz*6pg0Is51^vjODxO@$ITxtFfIt9!dP8a@~12bXqA( zEv2(N@{uudRrJB2I^wLZH;xm|Mp0kX-fr#MX`O9<`UeqXodGnY=!S*2h{hr-+nOyx z8eiToo?mCB-1}Zah1I$pXU^o9x5Ns3nj%FsG>YCSV%69z5xybK ziXQA1A8RR%X-(phVJYI{8&ei86ur(28MAQbVDYkUY!~{g!kHrKQrsdUMcg_|MC_?f zFIlm3r})?4<6_5>a`D;Va`6!UZXKK=zQ*6h<-!xYLp-~#Tzs>n{82F?MJy`E@10_y zwLv6Xu@xfP8tbvr;`UXYjN6wWTvm#BE6RA+)R#@1Jm~{*)nO536`=*!9y~-@`;xP_ zi7R$wXTP~uyu7UFO|fN&wP9y_;UaN-@lzgAWQ@|=lg|yVSSSWsPkD^t13co@bpTpJ z#gDPp;nbvsP1a5^Hzh48ZSX>outA(zvZEq7)f#qdx`-|pVNX?5mQ+-vCX2&sQpDRq zR_r-(cYiCYqAc|-@rTvMcytvx9<)w(w^!Bd$u+iFT4*WO-PI$Ino+aSKv ztu190$rU@r*L{ktG;4?_{*m_Nlc^19*%!0L*5INqOVW4lY!~0H++Ynqm!6oK-6RfM zn2#fC_UuhQ(GFbVvD>U!)^j`eCXe$}lvRjF*X*$R91*WLio_5j37uGWUuxB)R4Qr> zd0KeZZNR7+=-1IT8?0xHq0!0Xo_=5azHW~-ucGi#|C{ITJtsP~r~dWm;8YQE=A3vv z8u(Wv#fx`Ji`vUllhZ1ith9YdzY)4cJQiZb-jj4sMe;cJuAL%e&(js+*G7@`+z%&E zWnAi*)GFT!x9F<2W}UU%;`5*l)=m2ptv*&X`XkmySg~i17$c*_T`Rx0p11av#V5N9 zQ?s*ISBM8{tXUOh7MAm(vnW+GrHEeT_)`vAOs%L&tQM3q>)WYnl)a=su`qub+#do#V z9?TnN%q+4N;{O%mfnIy8BNfR_Vn;}kHA*zc-f{i}P*~%HZ9cV3tV&stdMzfTH9axG zigs6sFRS)gY1tywDk@vH^yFQh=@pe$Q;FzP-hSV?bJh{7y6U1^+!=*w+$mmjY^W?v zOR6mMyik^!TAG?VbKDs5puR_Zxi-a}G%Rt`S?lTKaaO$bjIeLF%B^T|K(}TY!!Z)E zYb|;xK3)w(L$kBR{mY8b@e|?%I)2Z-xN&9K=d7V`irz(5`?fblcoFJ4t*CS2!G7R| zp%2r{@jT9IYELa}S}q>G<+z9{PX?0`tJaPck;Jf~clo_f53WFc(C;oRQ>%ODts;Df z=)LC-5%LtcynWN&&W%a6Q1s`sB6Ne;EY9q^Yu}*wMb_D} zaUV4QORRTT<;J+^3i0WhB5UZbikX$5IuW_!oDq*)Fx1#@O#SRxT)yF4yLD1*kES*FZJ9M|@A`@gu}d$y zC3RxPIgtMf@%q3G=ufmbT53hLCS`)0D<_u`G3*k*jY$z7mZT&NEqLMl*-a(wJ9k#> z{EZbaBCWAIts#4pQ|DSYe^D_wb?}M7<4Amc6>06UhVDF3F*CkCC#^#KY+AEyP${~f zvOG0ydcrlY3cr~m?!S$2K3kcT7FU_pzVp}56)#)5YUj?!tZ~*I?c%5E4QJcMd3^qS zpBu7doA}rX@~bKlQDeoeDIz3AtQ;#s%8TE+U$~2BiGL3&A16LDQpCj))nm}#%mH^ui21Rkvi!IcXDdQ)2Yd4#je|ntY^*}<6ZUf;@IsQ+RIL? zPpzhfpW-g70J~&c6|*mjK0B^ic&+G#H^{|`l=0cwE5XfarS~ivlr|_0teZ9?O>8i& zvDR6T!hI|ESgD?*>}<#mkp(7kXIoz+#d}2m#`fei@o0UKb#7l$ny{}dBKa%!RuZc> zw;NaWZ->NccS-Oo4Mpwg&~L`D=#xncE5v_R7oBUbOsW)Tv5=K<@fgll@l>g`!Adu)$MTD1I zP5avm#XlO4TOXcqTNQ55bCop&vdYQ^r)Mv;##NQ1Ry3uiiASuW(q#*h(h^FNmX$n{ zRC%9>FtT)U>-S&mG?HCM_F2)bgT{f7h9p-!DsXlE@yrUbs(d+CzWUslitOYe;{3pJ z;a!^2@a3erS-4>>;uK$S!Z0OThD@L2al_`yTW?S zxXN|T0^QyRv2$eaGZhs{Q1XysJKN8nds;kyryz>+aMs&(oAOq<%3j zxuX56ohQmX4~t`AMJtjQiq9+eV2#dM(3KSx5AWPtA$)_LvZA5BKQG;IR(!H%!@0fU zRS4)uEmwiHOW4o@FZYE_@OZP80?~czo^#?3tLTXMhjUBXle6b`U?CUWn*P@+e-u={4?`UfHrbXUu%eHwRENUEa<=_$X7UAj~JnY??e(>{OdaG6( zMq~5#S06;rj9$%=WM@ivy7z30@L}&WWIz0L=_6ha%4RV}#2E5xlO`Ilt z;_UVQSdZ#>Ynj_U5FY>i@!^blNchyE>9=g~ZeeG;vV(hJ2k%bL%?{uS`NP)Jf9n0L zKD^2MUB#2$$+I_MzT<7I*c4v9d0r8&LiL-%7d{x?aKigrr|I72B?rBCmp6KQ7KWen z9-v8oTNn%f#qHV7JK&;6crQCBif-QOmD{|xmLs^yb$bT9BQ0RipV^~dUI71yVe`Dt z+H7z5q&uEW)&7LiYOf-#MA_IhuIk$xDLJZ}!> z*N`9n^f2$$lx^PHns8%HjrV@rm{)OdA9C}Iw{sEN%9f#bV3u+mI-U$2^lG2ir@MGa6bPi_PUkd!z{|pE!QeXFOZDLGkN*7xbYz?G zT6a|IQ0{7PVyovMv}L0BsY@-)) zUEuh81@W-9Z_~-wdNUb_-!X(=2x{y=K4mFbQ{z*H|Q^J>uLpzg-3boc(O%o>nI@ZOc>xKn_i z0{t5FFImpD5UmKn4;k+s#;FEa0nYWnIl%Y2S(&AvH&bd2zyyMO5dAdhXh*jy(jpQcCA5r;`L1lNX1J1TyV z^e37RVt;8s0VhI&1tmZ}qZLU&Ao(#hrD#L>1Yo6TL%9mY7B(H8;;4nQCGf}LTxY{| zAo61a|1}&9CjE`VVbcAAYr~|kDSnVNj2ya7ZJ0D&a4blgsrjVb>PMXrmmkyF1BXnJ zyehDO+72o%Nee_m{#t^ZuOOK6OGM9SoHyVCPQD6Ly;Lcm!q9(8=oAymcHAG1=8z6h zI83@$aBY~Bn+W|TGu}0DFxjsvPgpi>N=+8l6q3~f+4beu2=4|s>LtBb;V|h|!L?!1 z-zt8PRKD_p;w9aw`J}rA*M>=-(|po>nor7|i~c;^1OG#C$OBa~*q5DG;C&U2F-Tui zI86G1;My=L_cQvn9)tf=%_BXbaF{d$qX`=aDR(UT<7L8sf##83sBoBcfZ*CN>0rgT zjfW%9t8ii`=xYjxNsnO}kLi(qDmWG-3V`n zIJ7+yZt)ZTj{!D9mw2f3+E&^_Py&Y-B%4w-pI|Fo3#v`&9@tFJVJO|oQv^D|IK?gYSNxX@gPY{L!pM?EK zjBxaio$zoAcB+1xN%PS;h)LOFi0=kvr*WOjH=E8wK06V2y1LGg&7^;Y!-?1=-0bQ) z{Wp{H%f4Wfu(!byl11nwR6@EE4r~&3H3*v?2gts5DLM;93?&jeZP&uq$lB^kA&aW zggz4PS_GHmUvP{_dQ!1Tu1HsG(lKz5z8YkyW|Q8l*dz}LEczWt8}xeWBWa}=BO5;*81nJln~WIG)7k-jDD$VVUx&sFR|7xWZ3 zijYo+gAx+%EJ89Q(eso9>0&rYki4$hq$d@-pewd-z(Im!j=&<4wdX4xq<6qUg5+a? zMQt%iX2Kysk~{@Tw!=vVKz}Rj2+7L=i%1q;pd?6_3huv|^z9ysPulN7(M@s<92Jtz z5_W{7PGAv7*=0SI1SvOoz$lVKnoW9I*b$OnUZkW+x5FW0BrgdpA~^-e6iK;_0um(L z{Xq5}Q0{^Nn}jb9lTFH(g~8?~g_aj9Hfd)#uu1reE9@hY@0}nb>CM89kaX>%B9iiH zJtC4^quHdh6q|%!e1krc{ctpd^etgWNKOhYA}Q&sBuE#-K{W}V&qD`E?<^%jngs_5 zlBi~rRw?#TkQ2flxta7-e-)FIk9$2QT)LTHG91k!Erx^2c_80ckc3Z$kv>VqKqX9C z2?t@4l>&=M!j~%v(k_B8+f2&08ko$hpnnxSYBTAq!HQ2B72JO_DX*lIC;bx~3?RuI zqS&Mt!odKNF#?N7Zh~V((zU{lklZP-h-4QWB}ln<9Xd!p6j(&^8Jz13+DzJGsFEff z4af2Ui49k5(p%wRAIbMMoAjr`jyw#qO+gYhBPb%dcZAaMB>}CcP657x%B05qzDksZv_kraE++WB5?lH`RBPN{!hjd741QwC3gkvdlqQg0k>kQjW`UAoJ zHj_R8hnOUs)=(koS#V&JWC<)H$%Uf?=@?;0NG8C+#2qUMI*nE`q~C)>y^&lhFhUYh zT#~!ssF3sr!j6zUFR+N)icY{$g7kA?M>>r`Cxj!Lln%C%tQ1&u56Djxm*fwMOTuk2 zj7NG{u}Qj&RqU~#Gc+b$1qan6cW5^0-HQDnNT+csW)|okjY$u|A?qY#u2LeT+^qnG zBsT~w;!@CUic7Ldakqjzsknat*{vYSs{)HiYR4P~?_)|R9)e9WP0T0xrGg~0FdY&Rf(PM(4mQYdCW?2}K?LjJ zU?<6Y7id1g`*7fs=)0T;>Uo!=??N7^XV3g6?l>e70(G~MPcjrv`0RN)`w!Uc^Kdqt zxCiwGBs%+B{Mp}9zX#>;B3!_k!W?TGwulYCxl+_`sVDdy91JDVwrvsHv<+M8eKu^d zHu#EqWBp~ie4%C@U^$#l_AXV58|w*Jb^)i5M4PkGUnCp-$!_!~yYbtS-BEu6+51AW zm`}nAN1^SgXMQ)UI@(cB@QkV>k~SA=A%gaBSO+6{tgq%1JPQXti8geH7+QCk79v;! zhYXYGF?&Zn!Sit73qci&MI66d!huiH-tY;|5q>_2F8>|=g4iJiQK=flj(UQna426A z4hxb3!Fw`POd(0ZxFCFj3^i7e=(e=O7U&Z}+|t3dajNhN@Yo(>d&)MeZsf6!)0}E2 z!R1ZqLAd5z7Ch^`IoIEr*~>Wq{SH)j(Czh9#%Qo}d;Jdpc$>?6SzmkI?r$L5{pGUV z-$1t8{M^|Jt9x*0XH)D%s?gZ7#fBCzv>Xnd$b`Ow`A{3oP(n`i0VgGekQ*$a%1Eq8 z!w!EqMB?O0&5~^V7(yB)G@qf2?^|VUY=KD|99YM%z{L#?kmNsbt_+DPod+P*2Ze)F zI5S!+lcWNYw!@^jw$_ip{G}ESWw*7S>Zk+qkD(R43n%0>MH;mqj+peHaA?^iG>~lCHy@6el(s^I=Iw?9 zG{#ZFSVwHkBR2Ly{J6G`Y-1j=shKnFV`(v*RM}T#?8Bvq=3OTy6_L`Wwsge5zB{_wXFT!EqGm={& z^*Efbll=l-zU1rEM;4{1&-}WagIhnikW<5+PBDq*-n4rY&^U}D4P?5Ux6bg z<$TXq4I!(jAfd?StYvGAk#H?B){gC3<8;IK9QAJ;*i+zqS)q3>oC|5visr$Sb+9jW zjERUsPq5I|)bBsg)4GjW*e@lV4u=Bd-6t=9zOw9skTDW! zTi(y%{j;$0jmqutswFvFhL3{v7955-p(@yx4B!1-C3CNW+-%3028UEX205p2R~>`+%;J>54FQA8O~QckHPyS92#nnbiV}K7Bn*G+>P*lMV_Mbs3LXls<3AITz4AqlGt$^UOOE`XY!iN=Vr zwF`=|01np%wt8M40ej?O=>^Vr#bEMrI1b;WTsKDsNgh(r#HR%3PAx=1#ONa1q}mNJ z)U&$+6N_U3BB|#?1tyZOrS`#kdp}uvFEDD%s0}+fVC(UDstH~J>6;`*KFMl0UV2Gy zQ8-8%S2%2U58AK{|FAK-kFFWAt6#FBwE_(g>77d!#V z12_y>B$vUVaW>jU-Js*SxH)3PXW%eMHP)vPX*KIajgGsnS==Wfg+@W5g|}K^Ut`&Z za4KY@+YkCCoNp>;8qWXK<^ExvEo z>)|BiRsgnk@o-s;HzeZWD%c;5$Fwr$mIc6SB)#WcDGVVh=Lc-gQAoagAE;x#yQ+L2 zsAImFSqPcj0h+u4n#=$)D_pAtG#LRj*#I<|0HoE=zyTVYABUZM97mhwv79pWlr>Z` zlc=FnVyUj7Q+2I%wct8C&{r#`>Wtkety6Wza_aI`%Bec$<0o(oAXODq^Re8w>Iynl z$9z4eD(F-l0c#6mhRLL)VX`S6))kj8(e6lewVkT-RokgLQw02Ck1B#1p?oX}Ehp;; z_*_yvrpcmT`YP_Ezc^0Tonwom-)3KNob(sRNhyx6&`_a@B#8FPc?zj+yC>^>#dK1N ziA945zLtAZ3P!iwlm3=_vd&i;C+mDI_oTlFPTC@9kCu84oafXW7NE1es@|8^RrS8k zxvJimzg6`!kq^}gp}=SRs(PQntLjY)MTxGeXZ01qp^`|V0wW~X!-{Ml*;rL? zYSMQx8-xrLNtY`WqH1oPKMU*pSy<=K!n*o7i7Yhvv#`#eg?0WctgAQnp<;a2C9VO! z7PQrG$5y``TkB1;LGkaEhdX+3+gk7IMqBHB<+{~x)KLzT7}yL@#q0U;$48X@6RepK^~7}xHF zgCLtlK;2W5s1dA)?Sl_JAiErd4?SSsvE>f}=uXcfzehEdhd?+yLmeMbn8A6uG4~eq z-#Gg)9-kz-a$~*e%23_tua!oBtu)q~QCP%$t-aA-D~cYps+?>P=zZ5Z60N3IxQgUW`Y!X5wpOBXK-2E99{uUVNugf zqA6d9>OHsl%jY&JA8JF6Zu9q^+v<%*2{AfZ^|y=8Le{K$lw~K47b1yyVsHVURsS9i z7pBDHMSG3f0-=XRFyCl?9o{#EWg92G{m!F~DZI&e9S)Fdq{k)GR`4VQzl6hVhJ@eS zg4J8=8H@8&@$hjn%T7F0(nCGL*;>zX%Yl=S?zns8y^(m>Lf=tMHgR9%ARgnIML-k7 z_)U&>!;DwOe4EJ^;8hz}3i!lbJ!UW9R7pMaE-+uE@mSBT+C?UUpvB`g|-o!XXtt27d_-kdL#u@Zw859YU)_u#kegM6i&AaWHS*QlFBD zW|Qo2KK2K|p|%)JJ*JwH5VRF{8H8#?u!tlE$2%m_T7`q8OBD_$jFo5aG?ot?Oo3kv zF>2&$25GBIU5(tBz#Y#wPLb@jSbfc+AsJ@t73yp>-}C#vc+UfYLJR0jc78 zDeMBHz*n5z5Ql~#IukCC!nU>Y3_{*kp^3OQ^jf4s`0DF9<89F}vik~BC4OT(M#UkaDvEJmMA zEF`@P-oN0O&C{T*dN5_%YfSJNcW*AFl%zHLFIthl6Qs^%qN|8xIUIWt=?aB|q^lGT za}ji@49!K|N8#x@oUbnSLm4gMNDK0@zycEPa6^IYs5c74!=+vO5Y_0D5YAY5Z5NLz zuPdP>7Y;);Z#nq<%XJn8P4FlLsZGfRCfL`17_kVBLt!G=j;;?P=utS-CJ8szA?>a8 z%5893I=%b;(<`D*5DXo|o=G07aI_|!5gzDY_lLZZ_+waln} zSgSpwM)%tkY>gTN%)LD%7D<9d#&}eb*~{dsttTM#tO(jJx(D7jo3qAUguw<5v(eoG zrYXbQE#jFMZK-wWIr3?IdCX85}nREzi?t= zeLf_pAJuJ=2|6{WR%|xfi~zX1oy|U(rxU%gFBDuRN+KjW#YTUMiT=!-JqyQ5r~PB# zh)Jix!EBQ@MVVg)mx5Np`PzpG*0o2;O(J3EVm*7QPh9yL^9^9d;m{L!bFe|Wp>4|x z5u$c(7BZA8`@RHgbX-1@p$;WkkdU+u>kEYL=q-`iJhw<|ExaQeJsS=xIq~7cTA%i> z5$6$!QPdB}Jlk^A>!ajiC%fHp;DPjM;Bju=OglTg^6{cQ1xepTsP;AqQ)EaAubK z2=IqK{}Et5fHUED=ix~eobek=%}fNj{Ath(`8==gAm!1cdNn~y8EUxKYOa0n%7-%k?z8`9)Gs4v}T z2Vu`590W=BUq)EOHFfTX0OSmxTatX&hFQ?I84i8zR2{)@M129t?fofQz+G*BhZB*v zp!f)!cnDfZDupDS;DXK~47Eh(s{oSza1w!lpT2|9BoR0jfoO&bFy+L2(x6t(rm*4B z|12DoHP&AR^Jt=YjFEn66U%7gz?{fpKC`Hm-Busf%Fs8BDvGy84*7*a6az^gW|%j@ ze0R;So_6??rj8m2`+4-UXN$e2R>WiKMLd4Bw3cRUPnfz+c1*E87+{10&>f_HCqlAO zV37%>8md6CXTi`xa1bO}EU=K@Dom5&kC3#67${rj6^F|8}pc5@P()n+)?jKV@JI&jl|x! zo=`JdH0IN4rQBApZxkMCLkoRLud*eLa`Pp<%AfQqf6}Y$tj2UJOptvVxB4_r@oC)Z z*SOWMF|nXvIv$FF-HtsBjgo|Y2au#uK~oyw`kTQ0QWix+Q0L=S6Chzh`v!#F@bXir zzPN_P2KNqvnwrOGe<_wa;Cuzjm)`U~z(aMDTB(;o(Yg=Sapw|W>lDvO#Nt~L;xU$X z27_mh`V8PV^Bxjbgyc7HY@Vc#DI6r_hc&?ulky9zz-dNnmjURIaOO%w{4+Qt-Bh;^ zm!LP{#KX1ti{OkTaUVDdB#8I|iKm%Bf~YT$nAcB?_Fd3?3=S=J_AtkpiuDXY?ndJo7=WLT!&Vkt$N{-# z#f@lyFHBIo#Q|TOh`r5lfJW&*q3~Svz!a?11hJ=$xVz7PS1y_ioC)VATKD_>pTX32 zV-w+K`@NB8a{q!eev|GAq}yB4!7jR@JA)SkPx1Mg?vs*^3V##$J)fU%0(6vgRd^?0 zuGFSD%1=9P^7+>Q$9?|wz+B8V^0bp1c#PlJc_T`?5ia1&xEKXKUJ8B2QWW@dDfAg# zQQ)f3XS|03KP-hl<3o_63Vs5js$vGK;te<`Gy30#?tj6V@*(bsM2w%+%hZgYRruz& zlqdBt9@^vHdJ{=Jrqab@l3fMhiswGqKM4i@Uk~`99@y47H?amCuw`8N$bCx>Gl0p*EX4lpf&x<}sMxtiq#(S^hn#!_!G~ z=QunbR-Y)&!$;+G%@$`XAZM%3foC+o4a;M1N8^l59wo;k7WF~vvk6(L4$r@Zpd`wp zN7Zrk4$mbmh?Yl7aLaN&V0DS;oeHdu0OVQc>frMRA{-1qFIruIGtC_yW@-*&=W*id z(D8AC^l4!{tXSA`eDTQY>f)sik1s!y$AcaV(L)`c+e^T#I6SX_M;GvLMlx}5RiP@E ze3Nxp(fLuPfpf0-!jzP>7$WAn|MR&zRQr77haUm-5AMavU8 zR1w{VNV;a_$W`r}0JDqj@r+_3-RKIj4^&1`6O=d^!4XD<1o2Fi$C#Hp3Ae z^`fsT7{K-K(@6&5<^=3vaJU&{TkeL;LU{_2{#7L{H_9yz?t_oxCfoDa8S0~ zC$|RUGpD6|T+A&zW*7f@Oo+Ib+q{>+okN@$n3n>c!u>KI1e%vHcq`4h6!$UlZHQKx zpm65*2+|q(|B%lAq~F+SULi2)R<*>!9UM1D^1T4_W7%y%#gfN;b>>9?6aFs3SY~FY zzS+EQ!kZ9w63*;*=WcoKr8hr*!GRmfSy#LVG(YYD=az4?OZ($&_4;fs=pAt8M;X44 zXWo!A{4uyL@e>Z5aPdi(*^b=~i<5k|kd6+)UDxJES#FdzTcgcxX%o({$?en|qnsFW zv6OXdey{xx;r!eSx0jk-uzdW>6*05z*610BOUMMc?~Y;+`ap*JSkL5h*C%&qn(diJp1f>~Tiig|d%UW9PMG;nnjb>pBX8b9vkmiB!R*>J z@k|En;coz{HlTZ$@>)O%w_`&AL7skvpb7V{`q9wY=AJkBFt6^vwy;Dbul|F z%=QcJisR!Ov#G)C-Z1I6#MsL1O8-;3Mlbbo4};NX^iap`aApI7d4Jx7??o8*3Ye$- z=0U#M55Td3Wy)vsOv7v^F!2xnKgKuuO}a)eZQ@gY^Dy5$-#3r^jhu^XORG%PhxiDT zE14`4^HAG7={C=&O}t0Xh-dhD&{Yo?%Ep)iXMSuOd^BpFiW>e?82tHA@Orcj)|Gks zXC4Wf=Y&R{vV6E_9^Dx}d3;!B9?h9YUIiDar!Gd0r=d9Dg)we$%&+aGEc2Q5MWcTU8MF!3RIF@kiWZyBrH?>}~Snyr( zjl79(Zo$9H4kN!6>2a08$QyoDA#V{YM)D9~JTc;|+)mZ%Va z1tzc+qsyY@rMRild^`2U8MhTYo2$l7?;YQ1Yff=NWp!*aZ+)FI+ynBy&wtx!GUUH| zt;(scff4$StpbN#%){}aHIu7Q1(TvnVotF+X}U_^H&&UOzA-sDLo<7gnKZ3;=D@5$ zS!huFan8l@BEw-T#%KV9_UK?t04m0R^iH6K_}^F1-T04Q2;K?&zeG^S0ES~hML_H~ z8BPTddJWJUKrMk%oM(dujS3kw)*`N~C^;U4rqEQ2rdu@AqU$UwwP?OY6yN)1vDvDz#|7MdcP%SroHq ziABpST4m81i`H3mn?;Ql-DT0e7Hza>i$xDuwAG?*7Hzj^heeND^t44gE!u6-UW;C| z=oO0&SoDTPZ(DT8qQe$7S@f|*$1FN&(J70*vdC#++n+^Yi_$Dgwq6rp7EShQ&&nr{*&9vw`i%Kn;Z&A5LRTjl8 zT4K>Mi&k0m8z5dHGMt;kCfyA{nA?DN5=dPQ9)n4Pgtre!g&qRBOn7c9Oy2}80a90u z-vX(t#uq>;M}txg8V1C9TZS_iXb4b>vj7O|BH*n7!b}CIcN&hQ60{x&GbZpJ1H!!$ z&{?gqO;ykhK-q$x2O25pbs)|`Gn@%+Ftrv`3559x)w4hIc#t0gPMFnN^ zhd{hiW;i|5P0j}ashn2s?& z+%lj^5@Q>X3Vjbqr7;aR^NKeVxA6T%ZXM8MLC10X9uZX32@_R89{}YGI=eG&W(3^> zG*!^^SeTh6=p!Iy{W?qkmJ zwLr@S{Sio&+Mj`tG(rypsg~GxunE1)qCATVEV>#<#qBo4q;WBjYJUTORQ>)02+EPh zpMX{fN*ij@NVh1%qRtj|u_)7`@jzFLmY)Ny6!ag9GSDy<39rDS>w#7YZ@ES7hnt$2 z57bXWw*cKJ=m3z?Qi?)RR^sLYseIfHv`%;jff@vT1f*gF z&^=YFyAfy>LQ|aeK-Y@gKA;-~9RX4?hL1I4Y(5Yw5ti-%Qni&b&eVQ4AQfXE(5)gj z9!QnsTp-mOKLAoWzXBIk7zTZ{K-q$R2c&Fy8%XJEholth3)B*FDb5HWRnz4_afy3B z&~1Va0I7VmoM7tXDxjEz)&ePgKLuJZyuVo9r4zB3CA?ywLP4v5R2nIh%p4>IA#LGO zq)e1mXa?Fo=BtB*-jDwm2>P`}^8<$W6N?%=!^;R7v^ZqYYK#70(XJLI^ks|wV$u5+ z{nMh0!Y0OL7PU+@ylEB{Tg2I+vcBG;yDd6p5kDoR(v8!Xyr(Px;EsT|G4C0C)CMR!~DQ;YUkv;ng(6=S1Cf3>LoQWJWsMW0&q zl|`8Y%y`wqqFz8~$Qaj#TQt&!=2V~<$$i4Fb6qBgh)D(la)XdsY^JJ_P(HgudtF&nzXqGdMp1eQTWT!&sYSoDXpcolEDBz3;+|vC`9K&F(1v;esniAlbrK$rrdMb@kdm7U zq~vDX(1jMoZRkCgw-HFieZ=x!u;^tQ`ibRzZBgoAV?jEQ($Wz~S&(T%dHTEx9d3D} zEU(D&=2=v4(LGk~Vat02NTuGYtfmFJM7F};ct1K^O(aknA4y01M$MSw=(a(XD=0_~rX+!q_DVzUldG7)# zeMccb!FZfs`$kR<6#5uC%<{E&8Di-DG(WTi&mLl)lGp=*u?rfaSesdEON! zMjDW^v=flZTNlf_$npkTGy+J~??{U#+t6Z*YAm|Rq6Q!pcfCcMZRjHw?Eq3adIm_@ zchH7@V9`m7LRT8=TLGyU9WC!7i-uX0ZRN&W-VBS%EULF?y+uC-Qu%nuqCG(8%SiJE zkSfWKEoz@_c;5q3a#vVhE|AhU)}m`{=ygCUMz!VLXwl6!^a0Cz*z%sVygypr0n7Wl zMNL4e)J|AlXr!^KrA6H=>S+=Mb}zXZV^}Wl-w#HW$7A=?zN#0TlBa^ zzXwvOy<&NzeNR`zF zE4S66C#~F0AZ5#Li{7+y$E+M56)5X7EIJ2BSVtLCfZ>!~Pv%Eu=ci8frfJq|=q|)tSdA%$z*Yd_% z-dY%^V*JRWUt6@tq7h;KlEo(|D>GScJEIvPu*u@&8s0VTfpS zoGn1x;S!u*!PgJo1m{_B8k=!m2PcA6@`TJs;Jnw2^Eo(8mXj6Z-a7STEHA*9OYR}G zzpT>YSh4oGpkA|36_7Qjrp83@zC(uLDLQUYWL8i#>6f8pLJ08!e3|lMCfn?nsbyIH zUZ50f(#b~k(X19C6N3)cO!MCmEfWUY3;c2@NlBcU zNu25=4xd|@pECAGNu1v#arP#0-bvydPvW%jbqtkO&m>Mx5~nDMb3+nmc@pQIB+m9E z&I?JLLrI)3k~nQSsOX={MXw~zuq4j(Bu-fpXIT>G&Lqw+k~q&Lao$Pde3QiKz+tah zE_x(!u1w<0OyVp`;@q0Vxi5+H+awP6N1C51)en<6UnX%{b70m#73;zz&WI#VK@w+P z5{LW#%ui{)BZ>1s66c8|&Pz$050f}wCvn>GVxoU4_1;OGp-G&=W*odpzo4XQsZpcH zmg}3zFmO#0=SNALUnX&Wm&AEFiSvFEhlk3UpUPJ|-}OmxE=uAIP2xn7ICGLXi;_6& zk~o`^IFBZAxOdb1l!dP)asH9S!FP!4Pvnsqy*w1qACauIAet*4x~Nimr z>7?2P(dx32k>T=%F-y_ z*rOO0pluS zQGEU&QTe_|qpPE~4QTenVz!NIqScjFy}WXy-U%`(7DQtzH7k@?jV~-T&+6FX@|X>u z7=dxIxz^8D_H&TdoZ^xjEOT~rNwg&4n+x--PppWbZy7C5!iz&D7S18o`9FP znsdfglvEcMm( z>gHKOd(utB-*Uu^aW&&A3StWq858cP=)AJ#Y=0R}z_htpUUI6V=oIS193}v1o@vS% zh0?K(}tqQlsh=|)`V>CW@ zQC5w?Fv=nfh# z6wkqzYW#uu(Gq-i=FFm#B+O8*yYcJ=(vNLyk&$|a;-xwBqyEBFMKrata#UGjM4~aO z&6!VR_$@(^vXwR0Kf0{?%pNC=Wh$;yiDHts5n-KqanY}qT`31+USc58hS%T%bVg#u z{6J7r;i-|yiZU^=!E#1c6qhfpDXW=KSzKzFlFFE9tXYNY>KKhty*#N(*&NSkq$n^M zA1bSw>y->Om(87n!7{ftA($VniN;tz)ksXg25AZ=ca9pA^NSZ-#o9KsNnC_Sl~>Mb z7LsV#33f5ZUuoyFXXEwL(y{?IEO$JjGpym~rUs)OBmtfcl&S*w?m5HmIuBOq|l?z0X zwMBdwD@I3SC5fwv%}H~1K0da@>*PpW;aV+16%<#MWmR61DZl;$F6%#F@Z|$88`0&r@Q*ZiY zg8J7A$^W)rHkkhP!f%ryZx!4n*xTj*MR7;J8|$#mez4<`{)3ybUc|O@9%K69R>khb zX*}fy^lK*PLEmR(cs=|X#g?Tk$_>OuJ>PE~7VS| z+cp(Oxy!I=%lCT@cf)<}!Cq~YF@HAQ!Ohb>hwoFxe%=gx30dGx`C&(}YF5#uAh zg4G{qtlb%F7hiV@jJ5k>EgD{1y~|nJBcA?vKQvdw&X{t&bN$)*4S6Sy1ltf7<%^GqEoD(AY8V zM4DPDg-UL(D24Ijj(h0#vhu6mNTIc@LWDMrrPh4!`j<1qBYo|Jt@&Vz>jJNNBM*xP@n zY8>%dVHEX+DA9tZFTOf`dQY$iHL>=tKV86<_dd9*cW0WGr`o^t7j%HNpVy|Se(@9y zI@(dUzlJv(jx{Yts%v-FzMnJX+JVbIIr@6@`bX^tk$OC*%hvX_Z5x2lu#b4Ca1@i+ zGY=^v7?rj9(ATT?rq6B2=@QS$kfJ==y3zlW{HDhzqP(UwU4nSuUY@GF+kQuQc;Ate z|3UI-rlKzcrJLXMK3My9eOr2v-|d%|^t~xfzmgcLpqkgGO8@)c8ji}Eb!&E4sX$eK z8S%V~_{4Oy>TrBo+UlL*>zyh2k){Zuqe76wX8lRkH>A+M_Z_)d8|F_R`oho$U3;=4 ztS+iNjS_>>|9okb%J`=9|E=;a<^S|8^630&4S)Q@m*?lxWGIg`Js@J~-%)-_O6;wN z;D5`{jBg1~E+5HCKWo|<<&!KgS#kdN@*cDP%D+uf{qOW|`7U|(Pg7s@5c;qAPYP#c zPD^WuL}u-p+o;=rUU+`sh5Lp{(f5{QQS`b!qrau2zpc+fwX{Z9Jg4)X9KPS~po2Z1 z-8G)y#)n@Q<|PW#WFF2>aNDQ zzYjXAp85vTPVHL_d-mkXl6yR-YVFRpx6eV_TlLge3~ak*6g<+~mnszv&#(TbG?p2k zT#f{TlxPHl&HK^iVfY3Tc_26t$?=0-%pb*wP%MVfLDD_#)0dUig2gR~Bew@-2E zfXl@N4acNQtv*$1li8 zH{A;nl*XDTz(69ArZ5tT$4`RYuxI*|rZU(N&)W+FS1sv^f+|CP_N-kuihUbq^=c=c~*xI2?WIa zC#Q<~kIZ0<@v+|{RZLFWuKfl4NR*Fek8EaGb~+Wu0N3XonldF4@08#4*ypED|8@Dn zx$(S%JJQhJ<~HOVcqi}BUl$yBYuYP+U2rg-_ew+FD{tk!^6rs0TE{TSd873b`M(VR z-}^-viM@N|oi06^%Ap83$3TMdJ{v>epPMOE1RjxP#fjE|h<5 z1(!84W0je;HPK9dVKjyhCS_h&lUY`g8Ji!?td1_M#W#(jrJ3flNM~Lj3JVH(IrLWV z>=K#JwfXCvrl?qu*6{rGry~VTm!p9+VA9Ec#u@67(FnHJW4WHnm=K>n;q#pHf~fiZ zwQcs~aL$X_r*!Xln6on{*pRv>CzJdsQ!v5ljPd^@bmwG1x02JBSv#MU{KhAy#UnvX zlK0oTm>=)`L(}=SsY9*`u1JaJz7U>;>9d(1V?5GBM=h=j>G9>bDjkkb%UJt)+jU!z zYDoi-kH_Z)Dlt9 zR^G{L+P90>AD{hQjWovtvHxw<%Nh1d`$)4X`~!+*7+lB{kmrWin;w){nD94zX(r~0 z`HU~UM@-!35JA!_PfpJ#zd|R`lt+0f)8zS`PkxfoFY>I9wEwEVE9A{oPRw}+1)}Rt zUtgc#J`giW=Zq{*o>uNVQvE6KN2Wbd^&R2)Iy^Z(N9uh?F8$8)P_;U2;aKo4JS?TfGjHbJw4HuQ}`QS_p z7yjXIDFyL`gVER5Pkr*~!14U1pB|GQjJ{+#*MHTQ`z`vew))=8Zz}jseKP;$6x>ch z(;`!v?nIYW?UUitX#Bn-??Q>bFeloRx*z$L@?g2?^2mdE#{Tb=N5vWWjy`$a-fMB6 zlg8Vl`116oX)pvs6NdCOY2aw}%jMQ~#o+b1_dXpsCHJZlcI4`Rp$+-g4|w~GIxy;* zT8ggP?(u2q7}Oiyj87Vj>cAb``l=@5c|PbM-S7i_`>1w+1(O8fN{XCjLP23;9nn7#J%SS}ZJVwc934qSVB#l`WF!y9HD z?*BQ~9fH3>(RYYXJB;FrG=2Grlnz)$qlbL6?EU^bO@meTFgI&IUy;>+e?#p7s5shk z)Uas>V(01{9FI>A(WqZ*cN`U*j{AH-)J)(IbBE^F~JOEf}~xFsyK3?eqO` zwO+Ba|7k2_6buf0nIA7?cM5#DdQWbCQwW(x*F>wx9+ER~6eK)9Df1Fw*g48zT=5w6sUdhn0eC~LRaj_ThryUMrNG;UVanU0EtKGEu_TP# z5}I@{zMBh8ZBkQ>rc_aEy=gri#%SF!a8cU04os>|NH}eIhm_s{iiTs`V>^a3w7oVG zDdT$%R#z&+GPIGffkt-JMr!X_)(#Qwq-_*~J14T2n%X)wEtT=lM&e;6eoi2uOgr}i zn05(r+ND!KawMA0OC*c07bgi_MVOgL1N*GA0#~LSjH6ebX7MC3Kgol+U<#JILDvzFv(v;?2sp!0+- zw~x<@GU=PJilJFPFG4RlFVJ5!PfxuXt+QXq>ED53{ZrBM+QWoP2Wrj$U!sUOFkxE4 zutCi;od~#0M@Giwi)-2l?ZqqQl6fhXAqfu+8A=251JhDqpcMJARCw@d9I*?AjPT_E z^?U_$fN!g1>3pdY%a(jWdZgdNgngrQnQ4P^5}7kKo!d&+7QVff8elDqwyLB-B$SQu znJn#SY%AE*4uv^Rl`3OjMf>pu7{8K)iU}wL+Z`t+JS@CPJ}(MlvN4PaMEpt1hki{H z>w>b$_a|l=6#DF5JY?a;nGcBY`PIxE{r%NI)+II7C6}0IP$f=u=p_r5R^gMbHJ7L- z&wU5rL#>xdR6a@K&kdxM%*P{LPd}S>yoXD{4jS)-fcw`#E3~yxRUy8i>%JM7g?(FY zcPCVV^F-XY0yPM8y9YzX^u8VVpf|nY6z(Q>-_fCIp~RPK-FG!JJru33&cPNY$9+$; zGRT@(Tyult9@4DNq2k(DC7!A;z#b0w{lKHJ+wI;Zgy;KJYG;(={!Mew3#kX|ql@vW z-crZ?yXJQdRbadQNa$HqT;jNg0~5u_^FtNtxuN@kPAoH2l{>dQ#`9Ag_rn0ce&%-X zkrHJ&eH6G_lI|6%sxGUno)lfIwxzgDI-nm?$M!47J)*S@PT|Uh`w#6Mj^rw1#pUX8 zrsE#f{OpkWY_a=s;HcP@8!F?575CG?eDRMBRpc#+MJwdn#qMz(ZEC34$2}4FJtn+v z_vxr6JcD%HlYvhq^2`t(#g{FLlAD8v#qMW1{&k@xc=TTa(a!_n?=fy^s7g2^tLHiH z7lAsd*!iI)*q_KQgdUWC5me|6uJKi@PJac z`;t(VeR|3?ztT~bg|OvEJylIa`Z^H8mBQ=3DiEqt8$cwPZzPV_eN7;=M6nZ5P6w_- zI$rm62xFa2ibhM>E*$qp;osJbkMnlifP24$G$N5i3`xj!Ss-5byAXu^RF3PpDJXKU z`@Mmbw^+|X_a+h87zpVvJX2#xbGHOSwf!BprOOj+z3vYnX*9_Bj+^SfDoJjGUUDR{ z);h865JOSRH<=wb-DSCX-FHCLa7DbG7JobtYW4|dx4p~m>2-fP5GvMR&2~GwE!&f~ z6Iu$<0UY-%ca9i!08)i&KZx7OEySmuyzXy6rQvnf+TMnod_LPfN9#HS4$F(D4!P%Q z=E*>4j_=eWw~PA>dJw9^75>z+1<^`uRB+GJYVUG6h;Z)?dr?>Sb;<0#Zm1M}l3O~E z12oreF2?|``(D=!TKd>5@AccZmbWKYq*^4TYSFdkRbWla zCvMK-^7e7?bA#xUF{ec^9AqVjgA-BXEyv)W*UjZ8n_CeFz3%RB;R)fZ;OamwuZQ~q z27L^dPO91b<2$cwpcj+yl(VR*R?2}x>yn)EO6)B37P%={9p&h{1p6;a9dEIFu`t4+ zC9(<0@s_wn!bxLy#(Ew1IC@LnYGI~_mJ}?-C)T|>cfBw&LQ6(tY?KWjUcLK>Fgu5q z$o?&FnU?B;uB7&FdCN5`6E<;Q61T!sV^@WWutM9{L#gFA+p86d z)B!)@tHM|)64r)&v<=&Qn``k8qG9E9vd* zl|ZN4JsqP@Rh4Yi@y_r4@WaBk4CE;??Ufp5zIz&uC1=d4ndAW zj@Q%sweWLM9emdy94v!%Y3${yYVUxz4NJcbi_2Gs41hQ*BOI)NN6E8*eDb=faO=DZ zXQ`-g2DRa!g809;;Vhgp;v1oNMTj-T;z|f1z6VCT081=ccUN#*%f*uAr^2PTFhhtt zRN}H66JcOqBhhFiOD>@nK?`lrPiznof*t~K!@<(ZTJDkz2XBMFWec{QYr?yL(}@G^ z&5)>09`wAH?;)%McB?tL!6h}A0%z1Z!DZq8tXn6e+6gWf#ofahrE{F%iacDQ&~h{C zoZw29pxZqoqrwTUqP1@K&K)@i4c@q3%@{M}w8G#`Y696cBZ_e`xLWzn?|3yu*Kmg6 zcF)YHE0~Xy6rAANo|1GAr{yMO%S&sy5;mPhJU#gG2f!VNGTtkX$VAcU*aIQKS9gdn zm{H>d_n$2|oFV5#1Yg@J-U%6HHL86F4=7tB88Y2)f`3tS&Z&+qn={W_^qy)>GsD4D z{BIZNg#T(FX~}x@O47T7(~3CFYte2tJSkIPq!(_-&p>m)sL02eeqPIVD(RriUc6TA zR0)QimRZzOntlWI5clz(N}t^tm$eEE@HH`Y=A!pZx{B}c%Aa8GO8;1r35F`$Sd zP`xC5r-b98t_R1Z=?8^_(HfTtTx>BNNKccy1&r3Rfzw;2WiU*0horY$`!PCWTE~M# zycOw}N*s*N>c+=gnLbfC7@O71+woSVR|^Y+v)b6}-KY)3(5$8+H)#e2WqnuYt=24z z%4Xj0cxyB>mu6R#a=yuDk&d@EeYd1BmXjiNm1#(SPgoQ5=*oeijr>c@2gZ}fIc*zx zWiT9^hWZKzr+|~jAut?dt%if_P~jjeQH|8g8HGV@h!Dgs6%Nj~0;~@a0Jp(%cNlIP zA_P4Ng2-qo;oxQ~#;R$_n){~UMHi&hnvT74+qlF5r(8lIMVw>=I1B#UH2MGta;(t52 zCv9VmG1jwAFl~Z_vWRu3lGT@@7r;nNmwDPK4!^WROq%!m^hp>WQocZX-m|ukRpR=- zQ$jdl#^J8K^mu>JoKUEYF9A)SI~RMo9q*4iS{V0yVLShqm5?)1mLX)$QYY*^m%hm+ z`@BsS<1;4MdrZRLZMZ&fHthXLhR9HH^}I#8ufJ%uRdSib`?J*+4t{{bK)XT8;ULow z2ZOkMOXGm#$+@$kjvc}1AUGqGc{4m2H{f*=9FJ7vgf5tfQsULK1TQmSPqP#1rZ@p` zYH?2!>aND|V8;Ad4R_LqdMHLXW3Ie15W4Uzxq_xazzOy4BA#^l7=;r$YXg$w-HVeE zy7UN>=2D9j8ld7h8C87Y&Uk|vcyXiH2@PZuz$#G&4-;}igOoQdqe6LA`sq#wo}e2J z^`tIi?L{gO{`olj*9rAf2?bFu%y~FSBix|6yR#L`n>XCU*?U6QZBfHZd}cF=_I%6B zO_SxW_B@x@Z5_A-mbT~Fyl$Joa%Mf)qIn#i*XyqCpfp$Z*WUo+glYC*ZkV@d6OZ;ME#b1EU1 z758siB*U<l;27H(J%oGH3Ll~o6hEHaODAJF~~R-CJFgy5;CeD)m)1 zby<?w1>>tveHuA@44%=NC&4qS9J>mi(yzQU}yKH0DHbNa&!O&Dkp?|Fj z?8iC>i>RzZuOhA0E3n~EP4V1lZ0YRs=%OfWy;<{Ha?K0v>=xa~G1=inPIy?g!<82E z`;=K6!WsfId()fYwAZiTxJ7}suq9P{OWhv?j=>+QDVZN#P>f4P4C4ATk+(&=Lh>?8#~t39XB(md#|d{3uJN1?H*8RbqlJrT(zRfT&sJGV5n+BbS~=3&USoHU4FX~uCc45}`k9*R}oz!q{*@cIj+HbOOc$;okhX@3`7X63@` z_Lh5ME}wtF>N8#}pPQk`y*Ri{x^ACP8F-G{M@Q)wDicGlszgIl+WP9CfhqIYXtRQO z(i;Y2$(k#e{er3%u*N<%s`4;E$H;bC?xz7)2Zp1-S`nwa(}Ho9UWF>zLM`f~@HG>+ zNPE$a^Yoj0?sUz=EsW#N4rca+9B#DQt9Efs;9jUp6;Bs;ls6Brz=W#!Vv*zKc*-;| zIM-IpTyKi)&6SRu=jod-B{LPQ(OLq%8Qt4)$LR4ZT^3p$cf8jq8gNHcgEQLk+=MIJ z6ZCl9IaDj}Na7x2uH#PB+_OWa^3JQ`PSV_S&|NWt;i(5@Cu{Dx$Q!OlJpSFC5m<~2 zr5b;xJHs7uE{jhtP&3^h@_L7XvJCHE&c)l)jyp>aAgFW}G7_&H#bvm;%43)Ng||&A7=2Lp zfo-}ap%dcOc*p&v)|3&dtWe7d?jyGT`P59?_bXfdyi(v@bI0AT?dqZm`Pbf+l2)b~ zY9IB~P}?KrWA=yNc=t$XuTZhR)a>wh4~3OFr#;3+ewF~8BCrwJPBs1vceU61JQOI$ zvNfI>%k;H$tu}}kijry>S#Q=XTu#x3%9f0)$y-=kjCOyE4oJb(Tu#Mw*XeABm30l; zIyJ{Yj9a~pVlJ+<=8?yBfx$2(ReRIj1@6u8%eshL;p%k}Rb!PdZ$fx!P*-z?Jc_zh<=HG_5ADYCamlrJ5JUgsz6~i7qxvEbagu)KXm+ z28PsyzE!BIpc;L2P^c8EI~c`6RYmioc=6o5ETk?3>1tkgxwbqbR5iAE5kH9F4%QN# zLsd4JAzG{pA4=iLsN)U|snI!8wXR{>+e2Sp7I4AE9j>{!Ap9TZzCAvw;tczo-IH*D zK!U7_h!O-86hZ=sAPMBoHINVz5JfH$Ajl<udLght270l?6>a!1I4hR4mBH*W>!l4a6l#w`*NOh;a=xJl;5JTn`a)6p@f zdUjaV%&ny&N$#{%QzonWUCM}cDZ}%KHC1S{jPq1|oNsQUE@>+Cob~XPC`-{dy89+u z?{C%84l2E9&Hv*WA_ecozv@EcH_9Bl?V@C5Tfk0kT0X@ED$UUResz>zRkivBgd@cThg0 z#$hgN-sGi=(U(k6wG+9)@`#CBPbURk9k-BId#FxlXN3-nyO}o~@J*AbpliemKW=}( z&`CkVp{}%igGk<+rbv(Q|HtnDaGw&!K(_GALpvu1mZc*kaD|CXqhp zDFiJMbJXy3jhESJ%Mx&Yyet6;aehoCU{b?#VZ7{=VJ%11=x*^cFHv9F)sc1JqIlUN zp{O`7!;9l5iNdXFY>)VAVML7;_jGtJQ2<6yx^&%a)*|p79rFOs;kdcz|Hp|bInP^h z&e*^&dvI?nz!K3tqMI%MidlXXn|GYXN`xJ0_pYk?s1fqjiOnZ}ij%>__z_E6Ds%oE zr@Ept_uh+>FE3VvIdh$%!utwMj>F-FidlC-nX zpNlW!GyulzOgXRExzX;DrnRxgF27fF%J%x!}iA`HGK&Y6pWnblhfpji=!a@R+}7?Uq!KbIK{^n1F zyHxBmz&<4FN+mE9dl6{9O6frBzD588OxgKJk6U)L00t@-*hnKb;8-aN$VKHxlVlB2 z=CRlWL3657IT69aD^uKZW2GsfLOCYO!6Jh-SYcD+u)>N?jy1&mJdFu9Jq~r0cNJi_ z0KY|g5r_A)HC&neae<}f zICaC_JJtv}35BgQ=_qS#oCh~A?7GgIUc#guc+h@*POgW(+WaTRC zJK-MFR>1NU)?&utVkfZ|f@|RU^7HIgzOt_NAVGM|h}@82SYwn0HX5{`Z)=TJQQL&+ zIy9qlIoKK}wsgszDt^pIh%IT>cqLnh{(!9F)&z44D{gOWU0GVZ9Q9|Sl6l1ww?+U3 zDoyr#(C(FClL@jw-c4gzMN0Uf$GC7RLesAIUs2aDAe&_UflG&Seerp!zNBIt zra0SOBgBwj=xw(f&h^_%xv1H01UBn?1Y9Da4YTPkrTO1AB7Mn5K;?$#UF=|*8#(1GC+c`8vzIIn}Q=U&=YG$+> zpr$l@6+^{*Tf2dB&z>n3b=###YmcwuYNOpCY4G|g(u{VgPU2JyHrl001Lm2B80`j2 zLjqJ9?MC-O5HN`3{ztX>M@;_P7N@st(J6Em0(gCt7~>>({$X3 zkL}??B!a-nKqQ;kjlfqz7qLxG&h&DO0?V(Uu#4D~7lk{QA<<#i83SIqzQRpoa*5cs zt_0sjY>SId8OtpVRN0w(o!~Z8NO6;#l;Y?ux)cS0`9gquB9B9;J0tul81Ygx5ljx@#qtq+q(yfQVA!D%5)3Hk`=mFVY;}1P-QuGHln8s< z;`A=I4`H~DOQ*Tg(R87RRd{+3FR{sW5EMSTV&CS1zY)#;NWv`hAcvJmXcz znJW)7g>n|d?yMagxa%OYM`&9+0VQz$-j|Lz*dOhKIj(BoX(zad{>A{%URv)fDIGxW~xHxMGmOQQ# zGiZ*dGt>m68a!Pu_SkU<&P4|?&NMtXs7X#lT@Hq4DxiJbJY0xqcy3f?_NIOdpViEc z^wIXL5R*D`bXKW6Kt<*vhu@jtfy>J=^K)Kyxqpe+guKCGWpYM~Qq=&@-4=VHacekV zHJ3L4dhT%)O8xih2&~CkTs{XK*B>hcQ>^He8lIo1`N{;@mH(-l&J^?X%PP3m!M5Q( z6(wKXBFu!!b%*;Ec79yBGdKBw3O@(s=r}*9QWG8El1edZe@Fxv8(Yx(Sj=X|@H}kI z7IR#E5NFQib+3St^8vctauTCEn@sjG1?qw9Q8Yxh#o>=vbRZ9+xO=mgp)6Zhuy}V> zfvT{E|1%Zsd4<#O8$lx)OCQ@#>sr-HpI?R=ZH<&Wt8KA%C^r{a=@P@{9^7`wH-1K) z=<9a#typ$T`MhzJxQwbC@F)pi>(^CXfCM2_dJe2Mh( z&0V%208mbRS!3kO>oVUGaWCLhIh3=;%INp;ab?9CCl^)*od0_!*LazDsXn<~&zc}d zT0?#19OPRQrPJX)%p@pJ3giS{=J|X(Ta);9_Vmv6sTnnEvQ#+MS6Q|^M=T0kg;L2x zpLn@DnOMY~3ZC9m&o4sbU`>$|XVZOR5rh4j0Jc0`CzajctC+KTF|KhFTR*KC5}oav zBUZ1h>raW|FwZwfO)pqCNMxaJj>wvsGRTWj+HMhLZaHeA*9pk1`%oBq*w$)p&_W-_ zTEp;OQo-qJ>sGc|@?|j$)}rk8G`ga%Bxaax>jie0e6sWOqFj46&gafX>m|A5gb^BD z`W@H!^un*1a*_2wE+E^@YJQ(emKHBwh79_9xSnbuJ219m}JE)Eg*70Om zI;w$C0)o65d0|`Z3fk5~P-$Cdk-2DBz>5~-1u!Bi-3$ys<^8LC|6x8Hgqsk|i#);y z^J|D+_7kKL5c0h%N|zXBcMlsOsQi5gob1vnxS7CFaG6qY?GQ)7WiAE1r2-6NmG5H5 z;ViX3(Y(cEpUcFpdq!V0dxm)nci0%M#nA?%$81)K4FcvpTDt0-(xSaKx5;?DqJ_5! z;bfbuaALD(&FwG5_|rG~jjh?<3iSlrN+G%&m{%zd8J zCYXN=p)>~^{27qn1HrG82rxbF%o2<;#sI5GvCm@;@`&+k1uXaDc?a&k)NvXl;?x(% zv93ZU4H7}ffoY&9x2Yn4b71a`0#|96X+mIN#blg&Fb8|+<9gVp-44Z1;7MUY5WZgP zp(k-(UZI8i8;y3 zOc`Vu#t^=r%*n#uv)vfNoeyTAS2U{ItpV6bAum=oims3bYpIN_cqa%U1S`g5bmjm0n-n2(8R z2so94y*uV6Q5tw>K@iVYh*m?{FwrJ#V#P(Q&gs}Nt4&S?^E!i{;dv8IcWI~9ZJlB! zM9gHE7mGSy4>yPKoQE?FEp#Vp%*Cwz@bVgjz6WbztoQSs%TLYzLJ1Xoif25Ol;EO5 zsiePBGMs67C0miSzd-0?Ji}KSW{PM+T#;JA+fEHLOQ<{vsVkAw{2W2OR+*(#j-bkH zs(cIfX$A!Q;u!(8`Bcjj8t(MEiMPkjVxdF76xE?v_>l@HWq2%7@npu|n3 z7h_>9JS?Fp0MoT>D2Kx(f98y#aGRO|=popR>;^2IUpi)*85wMV3n6+P9`pLt&tYtU z*eHHwInA*c{0&TR10Ea?hw7sPt;@<>Ug&Dhmn8+-p2l+)Zk}V%MM;^jvYXkqfR!ya z+vK}v?rJ~oiZ_>wBxrz+xABa(aqpzov%GDwak*uA^$XWcaQP*kZE&4>trH5r<9amT zi3X}q0-m=ZGYK-8{Dk$n!o~e+<{F_l3G%)0a5woDt#^&q%lBm}?9=f~g3QmUH~c+% zWfjBGMDsS0beV8ejAt_(exjA%<|uES>e4xS;pSH1d^Vg`;&~0u`;2tryw!0&ns4W7 z*w^9djF)>hWHNWEu%T?L>W{*XY06nLPwzG<{X0DQaPbhe@?%EkJp*LT&t7Ag_p+_? zY`3!U#`!S|qG!83Otf=9kwh6=HhCYf}4>#}N`3~-$*6v<(yhlR6 zNqvvQR0v|c*(W&8w0L+hM)jvmB;tYbU;D0mgpy)9?`B1h%EBl+H z43+wCGJNOIBWfS|)HsA{{@tvHmY49XgQnkWO@DVZL0Ft^H|5aqTxC=0^DkRA7puGG zzsv?`JBH^uX#7fR{Fl<$wv0;mOP4KSFZJJM6P&h3<8&6zhh;kH^l!&`j%xD6rYSSd z6fL~@90b|Pj}uFYy|K(_#*1Y}G16!!gmTL;LRmH+r|ruiS!CwzfTP|kCSeA}yh@Cm zFglRNd|~Wews;OEPQ=kVbBrk_q>X&t=1M)wWeAcG;w#XKjp}R|&!RgyM09+Xi-90s zPoe|3LIh(YBu1va=WIII+LI0NGtCdC!-WGq~otIVIm zkJLh7shG+bSq*UT444XG8e9fuIhe5(U=G90xC}I+^>{YJ)!;jU*28-I!(faw;z5BUnhGTucrLz`-E~ z0^xsNd%rXr9UTIyUJVpWN9HausJggIj33y=Fl$a=l}w$(QhPEq^CdD3qNzD3AmWvL zSnDs(!qoxhVMl#IA80h+GPz_Gx7~=xYP(LsS?JhC^?zuZh0uE?TCJC%`&+I1qgJ{< zc61LAQ%2@-xmkI;J%n>c<|lHW^7e#*v=&oL=BFmrU3?z;MIt;A5uR&co;+V(PGNdH zN$@#sBZ6=Y&p@%ZXUavTWe^;=RE~1kGBD{j0^{(M6I0RB&;yDbFg%HW)I2lzgougy+3`e(snGK0`c-nWxJD5_vWFIPh zpz2FS!=h$%WK&x%X9B9>^eH@9aNZ2(vU-<`aT)v=fX;on7!#vp4n+AjOxz@mnztJA zu4p={WuLiH#<3oHKfv<{Wb^VI-IZ?Lm9e`0!ua0z>tMDUoDIyA>TISP8YDsBU;ELC?1Vx9)!E)J3+5j$wj-v>?y z;xX5GQrVBckAAlGRCL8Q%IIW5dBTBMg zcDqLmw(H^M13cG5Hh+whinqJ{z1{Iw#;MlBLHZ8rZc}cN%Iex9a;H)hXq2mhAxnn5Ba_YMKJaH{dZJ@T79U^c?+c z>#5l0Wq#lhFOCYxZ^Lr{vJKkP545M4@B6^<^xUdg^FES^QwK%AW&kck4IJkr&PQ%# zAAP^Fd1W^(mI?Bi3|l=^y@_W8)ZL)fedbp8*$=B@_&%56I|OC_#IqaoP;xQ)2fu`(-s7E!E)|n)s&QPVCd#ZK=olDgg_vr?TU*YwEmyV) za;9yCnrTaNC9&|;X?<2of0NSGxUO>G(Tk>#tiDhI*r@|Bnv;+G9C;T!aow@&1FADQ z{fI)KCmvgcExI%#o6m?>G@r>(@id+csL7b*q*KHl!iW<>CPT9mib5{wOn}P>TZeym zGjEpuk2KIT9lR2T4Ny6_8qDv(;P<@&!lW!Vt(vE0nl(Ttd!b*!)weoCr=1WD5rc-) zs%%;e(^pQI2BJ@QMuc|E#Tb7vgzrFGH};jk^?nLvsSM?OSf(Yzi+OlNP&We+L9GYF zu^wCu#0*P|@a97SMuU%gD3(^@+>>iMxsxS&$`w%9u`33`aIs@DD?E4bh;QYYoh&u2 zJfLFgvRDYQ5IcR$&X$^LPl1eKCMu)Fh$V@=7NuBPD&pL?G~%7<4AN%Jn>!2p8Rv0k zq@N{5p-Bh|?-UKdk*omyoIqf%-;45MR3N&h`3+_`O#EoTpSaD>Fu3T$PfEczOyG!V z%W+HnDGOnme(#ZW zDc&c|`QD`I-tu(sg(=>O2PTZVcHvi_Oz{3?-TpOp;ozwg?JRHQ^cru66z|G(Z-;d6 z%4Bbc`QB4zU7x874}9rOnC@NSU$yvv$ zn>gLOYGc5ArpnXb^j|%}9_@X2?ePVu>-_iQ^~WzOO&Mhm z@^(y_KgydhzQ+yT4*PpwHGkCP?e^18Pxt;iKHYoI>iK!zKg7T5ZCqXFO|a+tN39t( zwrcyRYcm3wcE*CIKEdC@o_8$RZg*YS)7!pIAb-oq=o$2OOfI)~9ay-%=c)Ol%K~<< zO^PhEgAfLc=j(;`u0P^=Q$4RK{8YyFf`xWQxqs9hBLe~NSH|q+mwZ%qMBnPFe&IN7z*o+$Vire}CRhghBUz)ElW{$A6jXFPQ2DoMQU z{juf^rav%p`__Z=(-7>-WMFyoVRlS0($|XxTyRRZwEU?2zuK;An3z&i}EwC zo4n4>tayLpqV05PU(VK0BI{EG<#y$hzVw*P!paE5o)7v4+Ky-UCFuBr1T z+v$C-+*t0NKHfXj?_HHL!S0%2&zm*KTll=aYesGFFK7UQtlDb7tJvC^Wx6^p9 ze`D!GCEmo1-j&a14D`02-haX88D%dcCwdJ`$yngQRF#Q0lYwiMTTH`TYbRLN7F2As zkNUR&Tvlhh#*^JCE<0##_D<}uH)~(ks}RlVSS)z3ua4<>V@lEh<%$i;beFr_ptn3F zX>tcT+MCs}XfIvBzK@bW1bUYvKc-V0aKaHAuK@Z<;MHe0vh_AQ2} zQH7~2B^i#Vy0FX?V@$_!3ZU1y9j{MeypxsQOteLpyY#~U$q26qt|Lkx zTsQooG~w#t_sKYEVjuw$pw9_ou8M0iJ;9GFfp~{&`!PE0Jz|>$Ww;Xf-*jZc{`02z+c9UTR&;@brKD_!<8T{@D1 z^T!3VACloJSTD#r{!C3tl3~Hf&xsFLxXu+8$DT`9=dw>`An@Z7RbNoY4|jZ%DS#iB znSMwnDgK9LGXIN=6W$8QoGZMJeccb(*TWvkqvJEaRo*nfp1Pd)qM=avYw9}O1eyLW z8Pp>b*%{QdHw)#!sc&3;xR7;@?JL>>)t=2sNs^7MY|^qjI$`HjeJ8hG6*i}?b3R_T z2~K-ml#(>lX|d4~I&C|r&0Dq6vz-QaIvZ=zNN05%qZ(@`%$yK+m%BpY2#tCNwyaql zb4U=zOg#K?lKVYSC%sf0t5T9Yepefv({Yl^gm7lVosKsuwmVOp_QA2wguT!418w0X zl`f9`Y}jAwvY*~M-C#e^v3I50xD;c8lXOlRbK3WRm2LVTWc$Eh{x~N)2-Ha@w!JAy z<5P@@qS)y6oHMCE<@j9eX@$vN!VZI zN>}97jeAA+Bl<4oEY}2=j7s}us9Mp4hrQ0L|54sa1I{b;bm>Q*NAyP=d(IkRB&y3( z>vl}c1-b0qaYzQvALnhpFP=_2!buiPP-}lwJZHFSb5_Uc(I`9Rg3}^-E_ZqCTi&cv zr&WH6c@9Sw^?QP{chZg%7~38DXul9`nC=(mp*b;zysbq)Gdm{+DGO^b2j z5w*WDi%nX(aEUsFME$AbHtJVwA9S`-Lx*`C=d-iv0hVN_WJ$0k#pr;fkFPK;U141IAkCS05{OlPX2uJY2&)3zr3?@y-xZd(Dj z%keP7NGm08ld=FZlSu0&ZjtU*IO%?cgNPsX?ZAWRQS^Dq;=lOOb{ig~Gi~YEmE`~3 z?Gq5DBWP~aZVSPQ-y!@zjEC_cJt}#dl%!5 z6q3gTTT16INtVv(&Yhcpq?;m=p9{fhbn_?4M%@&NRK>qrVY5!y{yznCADn(5oR>x; zQR*na4>rG+${7MFSV(e4pwmeHgU4fRx9I*N5urkos|7oagh`8JbhKu|n1zSANtz>h zo3u>u0h^SYuPNhpR{{*GNahJvml10He%lJzF2^HE5NM_3ZPJZ`57?wZiCd(KU+ef^ z2W-2tC*2`=oAeRE2W--xN!%h;yw*_<>}h3Bx>NEt=^q6jut^U|T*sZ}!wMsPTk#e+QHwrpCv za+WVR!YB?-qKUbRG=cdo(jk(!NwWkW!1OP+lt|nn<<@O?UF3X6y1>#Nr2RO>bLaJq zc)Vy4bo&t%PIU>VKIjO$!pn``Qtx)*ztkHIJI&PZs@Lbx;z+q;T>)3i@rd#US}A#( zbc^5vHff#2Ez)|0lRm9*Cm9=H-mNgwy^^;{-x7SlCVgAt7OCQO*=qv!p|U6aSn@XM z7lIGiq+d$hB2~QBVW32sco;8IujFmgc7hMsq}&(oE;nMfM`2w+yGq_BO%{B>ChaA0 zi&XKeoHXEUP@1wQ9U^&~^cukjY*OwWcl(_QbC$wLb0lw*P7!>-CM}k@MXGom@7ciS zD0|YIByW?h5PZNUt(3S$s(7uV8rTM9Pa2fGO?sQ)12!pVo7~~28Jj%?M!G}tHtDm1 z57?yKWlndbiq~n^0BpCiC*3P~oAi+212!pllDqwGg84&*k$x`6bCyiICj#KL?dW z5`4fW<>p4}AmzSi_nVVCh70?=2XjHk;K2)!WU^#Q=Hu}gdHNOF7iQ@y^}(opbjU?} zs^A-s_R`nrdvlO-@8yt@ij;7sqYOcypUPdPlhbtf-}E}p;csR(M#9(O5q>xdZifP1 zFAx1B+;D9gr6iw9_D#5W8xI5qW6<~;JP>f4GpO_f`lq|XH~oLLuY>08Qaj0uf}Pe8 zdBT{Q#xzF}CwKSql#FH_r;vB!p=;8;k{6#?`Bd-$n=~SEi!>4QFf4SWNrLxVq!%ij zl)JgzAvy$i7O*%Lk=_%@cE*FA7F}K-SrR%_LQd*&y1Ex0>Lcwfd7E^I-~%@4P>EZl zoGW4&N%Iv>I!@uF+!O8&Bd58G6h>Msd7HEorh%!Cl)J9!jLF-X^_9@F;(v-0$s95l+fyDU38v@-}I)-~%=(H-Wp|ak74n z!br;`ZGk0o!Da^Xr;W>D_vc6)FN_NVbc6-kR=O9i2HwCE+l*hM)e?J9YjG+poko0OZn z-5v~tc@Q3`A{i;zQW8qKJmAVp79Kh#&5^uKx=`=|o0MC--5zkab_pJrstOpFD>2el zlDA1if)CiF+_3FdRR{BSg^}JXd7Jc?f)CiF+?(xoR}b^k3M1Vqd7Jcr-~%=(H(|To z9fJ9=!bp!w-X?7pe848WDF!H1r#Yih9Zy^$F&dcIU+{tmAp-Qx!?mfDYq%R z-Ek=@O<|-%ByW?J3O-kro=5$?)Y{0GN!;>F0j-GmxJDl2OWkVgZxagPl8BS(eC|p zV00z>A3n#S*QoG4=r|Py$FUN0UaAdnyBiNc(gJ$5ttouZe>5_FsFNcwm zDn1mx7LSN4#Y-H6q^~QS z^pL_yx$)SYsqX>%NZ6-7=z$&2(YeYS7bCj}C+HA>o-cWuw5Q+$HfgfN^>A4Zc^QF& zlku{+27x};g(kecq^*UxnZ$vei%59uh=b{iMR<#d1Il|rcnOGuw7SlNcXv2e;v9gy zR)P0ow1UMkKHhV24jcziz{L+aKJ=dP0BosOrn()zqiBtBOKU$X#{VHXoai5@_vU_HsZv#xUk_|7Kk}7UT9^-81e#zwlJc| z8xdMrh#L=h#X&1voI~Li2Is)xGcO-Frwvkz*9M%^4#~v>|E=ug84w=TZ)KrRX7J>F zD?53ZT^z3GY5H^8s-yBe8-GrFc@+M+%&4_EYR+Tjj(qg=HBVYAwDrkqo}_jhxDVLM zW6wO|?AW>wET`r~arZ%EPi_=yi6(!u;DpyM2{y2TiNKNfjkEIJ$7)(GkuP2^w3`K@vTsmSUf-%BaNg& zn(%yEYgimVivdMt<&m-&R3sjchqXZwIv(GO!DW&r6|{nNW#f^j7zfcqNV2T);L`U9 zh&1Mjr0=nphlY4S$Ps9JEQd#M9NXyW7{0pR67%Ea_!27tRdQlgLh|a{?t>tzfPhS3 zep}m7D-nJb+(Gy;F5}MDz;iCZ^%-{FvFtcpBJS@0n+sVvztZ4GxE%?ac@LpuuJkYQ z8$5^R05U^3FXSN3jR~K)u-4!8y$}-zj{HhoENjei0V17|6u5()gLb#vtefP``urfI zgD+V&FM#;p-4^-;-CajYDn;0wZ~F2hld+c0$1nNe$yl4HGxc3del9pxL^Qz*k1q;Mo-@K?i2jA7hcis%%8V#PG zZ{i)*xpTz<0rhDKUO_GHSmxEo&OOHlKQAV}xx&lOoeyX6qFwdH4PHS#PMo;oE$Fzn zRd~t^sO5J_4Bk$yJ}JbTc%2W{@MAUdidla2LVf{*xACg4aEQxYc%`-TRgSs65k;Q= zGI)z>wqISKy2XLTJ@#2ER?Jy#>^KK@6j&+Fj2XPWos9Sf7cV2^C4~n;2~Mss_<=yA z3%|#w(q&mCd!TY~wd#+*!&iR*}keAmXxR zUVp2yl6S2tmKXmsUwB1`a}^1{D4;WrpD%anp3^4r!dc$wS~zDxnZf&QwShO#irZd! z@2p^Wqic@3{e_puI{a~`n6NEJR$v6gpC$hDUo~o)^W#2_QFypFq!5qu`##)Rzj9X0 z9QiBICJ(^VU}I>Gm=6S&PMvjxTyGL_fw?XZ;*F`rD^x9BJg3qxug`WAsCSEF)fxjJPC^X*4?P>hUt<6-`ics1opAU2B4xX7T7d!Hw&%`+!Dd@Qdr5wp`I-h*u~%~ z1a}v><$`+y+zP?{Lvt6S^7;i<08VOIqPZu*$*`E{Qb{gNbJM}C6mAb{>|4zZz^b}* zaf9aG2De(c_!qca1eb|AD`OM{w?<%p04GzeQQNX_Cb2{$?X5y?2e`F@dlg)j;KsDa zl9k~6-~b~R)@ZI;b9La>3%TdPNf&?DwkI`rT65=jKno{a)Pa+l?*X?#VE+cku*4fC zn%|8Ay9ZoQaQne+5?p_@9hHI$gOh2$qO+s#4$b{mb8l(xx%4qU#oTB73}KPBuoNeW;>9^f8G<}uk{bsOK}1?ThX2We<6dIP{YrCppqxr9 zgb+yXF3r8Ixpz=Dr0s{AAt8>_jsn%jvONx4@v*B?13v8kH#Ypz;z zw`-2ezS2cE^o}LhM{``_l~|$XxFjpF#hROqQlc=;vE)eX9?dwSaJY9g*QB}6G&iT8Bez&{_iOGu&Hei-M{fQAhkIXh=>r|?KFz(M zxq~T=?KguQj`uyvvxj$&`Z<-r5 z)N%0$INMqVUBH*=6v8}8eFcqp_= zW1}=T2b>IjndZv1?Fw+x?S0zzAex+>>Y3zvRj%wQv!AX5zX)JDp<6CEN zGX2g2ho%yBrkA$8Tw^1&T!!YxYPl&IE7jaAZM#r&VQu>(&F#>(_koikeOuf9NptUO zx#L={%e7AE&)3{V;ABc(22Sd`THB7$T!xk_*Vq!xE!Vbdz)3B&+IG9j`we1Ye-KgajXt~Fx(sDo3+(9jONOMQPNzET__=Dq?aT^OUCu%v^NVae27E;uPypyf7e z+pU`0rseL@a!0l8G0in;xn?bQVW#8n#hU90PWsyqT(ZGdiw88eSIaeO?saW@1e|o?$#=pMuetNU$*^3lu@Rcf(6;&D zq?RQb+pgvA(%g@=?IYl%i+8l`pTWtJ{fU-qKgJ1FC(U&MCqva8oYaz~u`(@JuDK=J zb|pCJ;sK5A)pCuRdtKWe0ViF2qp?fJI-$BubC-jYp&A5Ex|pSHZ_?Z{Ew@8s_h{~? z+V)X!QcIJzJ+8Tkmit`G4Z({qUE+~>+wRiX%bMG(Z4ZKzzC|?mmFD6nI<`Z=$q-zlxsl*xEOWKoY|Smx+&azu z3Y^sPYt8)@oYb;Q%YCV_)B?xFP|XboCtYNLlcD!(EUe{zq`4j1_AQOQtGV~I?Z@Dx zzNATxzdmrX*7nidKyWey!!$P!oQ&H-%`Mip0dP|DCe8g)+x`}ubo(4Q>DxYS`?|LM zqvnok+YdDt0Vmy_)>!gnM{^&|^#dnEzfp6)(YDWM?)TdE1#mL-RfeOl8#o`Hc(E=f zLtm(|samdDW1BSgxW=B;m|;5lEO1g^AC2|X*jSBC)YxK;@xlY?_I8ccY3x~z?bO&Y zjWub^_Bdfl04Mbg*I2s7ZqV3lja6%Glg1v>*rOVIMPvIlc3fi-joDru7H~2w12mSZ zv56Yv+M|@K(3oFibsD=S#*S+YJARcueqv6=S7WIf zo361NG`2}&TQv5h#_Bb8RAa|9X2UBPj|6bi-=P{CuCW_5Hd|v`GNWPP#tv!h zh{jH8?3Bim+B;$Kfdg#B8>t!_sjqjnAmbhUA+n<6K$YGQpCnVK=={yn%sARm$mDcB0jDo0XT$=%Tlo^b1N$y6iwMV zWoZAN5<P;emgE`r`xX1Ib75XdCsf179-W0XvSkl`D- z?XN_korKIoZDdkzTDD|K8Ft^|*ICGPA=~CR8!jtUNsu8~38XFt*$SjS2I0*`hhmVY zfSim$UI4=PCy0vU5wLt`Mv(~Eh8Tnw4K>9eK4|6pFzV_`AW1Pu29VSkWC{?z9iy%m z0pVLRitsL=>KNp1Aayaw6F?ebkUc<}VvwUi_(qIsW=dqnAQs|O5rcFGQWt{^0#YA? zoq&)7y~t^&fNvQcC-5T0#~A|*h0L^X;m0>U$;QKTA35-MO6 zxd#YOZAKCHekx*+-9YMMkfT8AW022*9Ew2_kXI*Tke)zzd@<@5?*OTYLB;~%VZx}) z3?Muv7)6!<5eEQ4WT~qL!lQjrnY)1S&|VbzB@mvmiy{rwgN7)I`~^sI4Dt;S9xjW@ zT!a$GvsO`LC=ecjiXvm!z^k7OVM!ZgaT{b~8|02Q$Wv{Qm)juR3GV!)@7xLQ{3OCX zh0aeR7x0CneiG^51{vK3nc4@gB)vv{Id=6Z5yN$Uy|x4 zHTQ0Vq_sh^+aOcgAPZuUS@?n_zd7yvJO;isx#FfJ6%L@v>gpI*wJ@d3E1MfwFl)}- zxhu+6IwrC2T-huxUs~qi^H*@ko@24>CWoyE%;h=rfEwIV zjLqR>!+>U2mLhYKINxDw-O%l(-yLkK!uM%U5EQxOU9Od#e*s$c}p@Rv@|HFn3752lf88Sk0vpY=W zwLJJWeQ6k51!tM=xhz75`r&{XI-v<~2?68xAjx>#^I6iS?f*>5x#qOmN=T#{WYEx9 zTi#LXyDAoAcXUu1wzj!`)kQdgHV7ZE`?CbO`XS_oq`IUGV+MNJuU8|U|B^6AK0{azj+47ej?oqVrlk!b>-_5B?-;s`X!PMDwS#7_kdi zCWLd6LSKy7SCyV!Ydse#PCyx`wKgKYTap?xF)ae6B}w}-O(Rrjg-d)$!Ei~pP+`Kp zAl3xn#YvW^+Ns98(9y_a|3SdL)vGQw0&(HugcDDuoxVPF681=+;Ag&YUP8FQUWD^e zC_6=wTadR0_SP|2j(t+NAR$~LM3CH(5+Nbem+nh^i;Qqy(iAC0i6K%4+^hI>tIan< zIo-lJJrJkv;hba?fp(2nJ>*(Y{82AXwlKuOhPYavvAf9|D(*3*5ORg#jzy6>zZJzM zl#_g-vGzH}ul8mBXa1Jh;cRL{91_A)5`v$%gnV0O>hO#F&rHx}QNMc7RRMB7DV&Xn zC763g79}PA=nbfZO=DgYm4`h{vBa9k$d6A52NFUBO*N+zx7`V#)(WMyuy*DhKhYn> zA@QZ$UEY29rm-*IYlQL>8uMiy1&)si?(>bPN(cpxuPa1g!hz$7FHPO$36J${wRV|r z*1WYPKJlfAyUfreYxQ$|nR%g-W2j|jVdVaAM6|;t#}L1t1iwI)Yclu1w-a?T6+|== z!ZQ-g*F!TBV5`fNtba(7T3;4?jXVNX&B;t`nS8oEVCI+Dq20mV#;We9ju(u~PN?b< zp5g=Fq1LKKB@0d5XrV00^6{#s+&i);q3Ub2 zv*9A&OjNHn`neUskcF%u;q9jI)+7Km`*EZ7{?JD9Gxy$HwwiN4{rb)`FeX`CS+=}i z-;}|rmHmyrl>k8&FP>+>wr@(>umuLs%U;{J0)GGouQFQahbW%|*aj3&40}WGhVqUC z_vNA?4n1=QVcB^;{%yE5_h+5Hc+qb=*&Qw(8#)=;_BE<`PDQP+Iy@l(?}AXl(NM{u z6Q0oi+Og)yyrZEB6^XSU;I*}N$G6b3rQ~?^Sx?}?@U5u9hqn4I3|AcrHu|d1E(ui~ z3cMCBITGIbDCBAmB-Zfb1GVYZXoRY(j+?dV&nIsB4p4ZEwJ-ltGqgJtzx(T+wfVUy z#Pb{TvF#u{&7R+w2_|$nRGJIReVLG(G`9BcEl^p#ivchbH`PJO{Ko7amzlLI`fMFz zh9@Tl8#`T4-vU{3agH)Cd zZTp~2)S$*3F|UXG|LSP4p;IXM86(dr#QmJ$0~o zDD3Dm5w<6q5??lf5bQxXbR0d6e>9ysyY%XI35lh3++9zRsl){c&2;e zkJ>Ts3Yzv=X#;8}nRt<-l0h?ST~c*=H^binP02pX9#}icgV$|swiymI6`F5`M#)iG8@PASJNbYIoSOQ*m#gXBHPZBk~ z`3cB}$0V>wqUi2M5i?PCLz}n2U1;0w_+NYXLHutXgIB63`g@R$vdHf~+Y?@eipJKK z=7zFz(;BGd5o5zXI^Nojc^i5C-y+#U*}jm~C-R~+A!AsUMUn1lHva-)s9lj8+_R8+ zFY^?pHEbQ@6-8qdB0eRuSt-fy7Ao~25P0wOG$D&#jjRh$*nA3FLV;u9lB40OBgnq+ z%tPV4WBYPFefmq<*JyquDwB6ii#0-KKuSu=iMPVbea-72voE`k(HsDS_ieO&nlLdu zq%lXdL^TKe^R^arYs{%YcDLAJR!Ef(jXA4eFdBmq68su-)}r)*2$zjP3%SoTi>rTYR;r@ggxnwN^+fT9!o=hp?-TU`SU!S%K$@cfCV=hq(2dX;E;z;(v6w76gH^{vhr>C(aiOZF)g4dt8W;S!#eZI~!B;)Jf8dLK#sw$- zA?iOXVlirV6FPwpQFRG>+#P~dN$nH2af}zPV%M$^9TT6qA0@dqfiKfqt6gZ%?vJcm z%TsHawN?!yRahG71QiHcC}(2zI`)j(qq@}=zQ8U*$?;I}#L(H$gt5Cnif_!xgacd} z^?Yu)dI3r!fl`%{m3HdJ*S5v}!g2^IIL^*zrR6{iC(P8HI=nwC)U zfOS1XufdphK&59Es}#DtE0ThHaz}g}_!s)XHE$(ut43{no`FPAviaVDOa!;*O-??()=wVf!2%ZRM6D?wrW-Kjuu8P{erDYGK84s%#*w( z8k&C%A*X-L{w?~39FQyzdr@!_ke7v#k3JVk70wx;p+7p%R6rLq$BU=$+iW7(W?{>e z9+KrCL0Ao)5_td)!jIj0dzg5lty~P z-?Wyr(P2-l`kCV7Vc2J8e_Am;h)eejHD8OvlrFU+#lM#`@{I!9vi~h{mi|!`JUhz zbLB_`a#717vlJuJwf|yrVe}K|mLE7DgDX{B`-~3m&zv91>5Gs5)zLf))Eb5y&e7d32XCl*Q2rD@TX*qro=%bMbP><3Y+IBu~tw1ZaWdw>(ILDv( z+@avvcA>n3iFfAh50xAVp6%f8P+hg(NZd4v5)%^8j%~ZiLNWwiK@--PcL;GdP#oS0 zy?Nri>aXWwj5^kC|Ho`JXCuDwU$E7#{?-czrzHc;AdOLBvtSF4@2uu4KvcK`iBb+QPt<@sBWkd5lP&19EQgH zbjn5FZb%svmky`%6Os~Zo`ghrLPgDiRqev1v&V-@XNSAueOTH5zM`~->NRLuH$8|Z zMy0%ygQ&m3vz-z*{eex?+4hN>>cONnsF+o+>wy;eDR`=)egW&_I?UuGZp#N-E2>6X zOJm*1>Osn91P|7F;GR1v(3bs zaSSVS#eW{NvLkcj*0tWm8WSAe%tmQsyYwQ|NP&Oi#gC~Mu-o=S0!3%${>D6Z%+RdM z_`NOq3;8yy^u%sfQKV2RKyExv)1klBYkG> zhw#PW{8b=6>RIQX)*=%rv1TUoP^upb?O&V_DNsEed3O&&hmvR}ZmVTDG~;)tjOIkphJ%Sa?5&zyKu_F zS24Lz8d)d&Ob+cuI&3u2pDZ`;92@S^I*8@U@bZV1^Y2eGxL>&7i2&}&LvNqB0Ko}oW9I2d z4ob|(8CGKLY)08X+zNhU`agyLrIA1VT_g<>@vtyAN^@v863hQmIPVn(pZnPw^Il;_ zFwh0{MUe*~cVoEVg>cEv%%X5XJ*I>5ju#b1ZWHc(KtlV9BCD15(}^`#K}TlVTV~$Q zE+sEC&p~pjx`E7SpICDQQy}i5*L(my+6`3)J7D8jV$E*YqQas2$2J&`LTK7FmcT^m zQ*cs3Qu8RFVbOIBmu8~m+i?fIuPk5PwbLq8N+b zoRa^oz%e3e2^?$*?2kMG^K|f$A4>;28L(hWT;ishv%-_mt^U%;T4||Tz|Qc#c?RMU z-oef@@^aHe#!9xZ&Hn<=Ts;z=WWCIUMh3P6&oW;-re(zbs==a3=*A}D@2qu&k&C4V z0NzC}HPqPbkEUw#1N3U`&L$QhAut-D016D`c&5zWHL8xf}@ zymz8r_IgVrJ0%E#(#VsNZ@vn?yxbK*Y(5X1u-dMyk|cnt6he@mofcUIi*Ug!Y`ZW~ zQH7=lt)2|e0YoxqE!trks$^PnzN zQePN(Rmz7;>a$sGO0Bi;HJ^k-)pj*MDiZb;u~V!$i5f+f!2E}DSWqvjJoEcaS>_n5 zE;H!x1oWhX@Y{D0u=fR=@$+hXpN14i-ryuaPK9`Ftf~x)Hw@CY5E7zqh7r}GmhiTF;kYPr=x-GE zqq`Ey_eDEu7@0hW@$A0fck}~qK{5BA-wm%C^lp0{;-s*AdCp~tERAe|9=>b#F+asy z^@ZwPV$R$DjFgxUiAJjr^(``Gs9fO~OIzJfL~xo{Bd28l3@{0!}&p1T0F>4h(lduviN|>iw+#T~&P59?La}|FG^l`;M1WMd_C>uI- zpm{o0qr#q0$*IUBawVtaD?1HwgCXSW6Bz~^fy10X0y-sfg=56{mgWniW@r50gZ)FU z8YHm;Ta0RgA>j_rMh3n-@-tB0oAVf{8+2a2)Ti@Wtr=0>Y$wODI1H z5pdEIn*3kF5IPfjjq6{{kD(~b@i3y)|xS$&nv>9mf{Erh42)&>YZJ35jMXqKKb2xqQmp2MZ}ed_ zJTN>7UHx_4(^^yz#zZb*L$ud7VqL=e6A(gD7DxW@k;v6>{_t?=(8%jFp?xV$o)UQw zd^mq1k`XaV1d1_LVI-vFH*=`Op<8~x$X&`+e!s#3>(-S#;1Ja6-Rf-D>r-esOi;NO_n7V%s?K^QB(nG9|u!R?^V?{kSAer#3 zqCIBds?&R{K&lwNp59{zdW5sOo!)2rt?)(W(cnj(#Jl!DmY(EhC(O7`tUYqR?xOH= zD_E7_U4M1x3(Sv(Fim|bly@>*a4KAKGVSxU_pT~Ad2zw1;Mc~=D>i)1P2v|d1RLT{ zydc}-(9zK6!6q}bC+)rVhXXGJ8|)L0h%Q|4?E01W!qqLW)q6IaZCQ`&2SYUOs`tVO zbK>Te$Vx(w*IR^I)+cVh3FO4RvH6SI6Fk%LmQGu%pYMlvoEQ=84Mq}X9*&6jooes% zFiuax+vh#z>rDH)S+#{2gvH;I5j@k*UlqOp{V1s+O|C95bNoqLrg~cvpM1^U-E5By zd=dIeG)f|GW&H5wIMZ=ub9i01DbvFFK2-2u{Z$l>)A^U!{==a&;Zf!pOn{AOT;D5< z>E5&b_mtLJUePtHmXar)K+#22J5e2KJn??p^>Pt@teA`0hJvKvHyu~@ugy6XD)JqU zG-f3u%ZyM~x8TPZg>^>PeSTwBk0f)3Dt|3~?vFsEZg4O3tntjoQ-^0Co_3evt*)MK zF!P}tpWq3*F-x>Ep^K=|GG?STNS!d5Mp}dPA@Lei<3H?oH`!aK zn6hw5q4tNA8!k#2a3ZCdtwKI2?ftDY%&k*AyFa$2yY@$0yJSPCU8cQ{8TRg5v%R}N z?$-Wj)OAv<>)jvOQLh=fsDcJK%JyuX0S!sJo0O6`smnqz+8<4PsXM5SNyu#fwu6G4JqbsD}M2yymuc z+wd{ljL=^~Gmi(qS)X{@lgLrbQ6n|Ghh{bjXfL49$;O&oxG^D&rP~pWSQZM^4giuE z3;`T*KW!6(Rp1+IGQmU8X#NEMP?HZw*twqryV|@vi!g}9YTPmNB>Mgzuibe>BQ&b>v)?79abezB_&uCOeJg=!=KcVArq;%*7mer@+9VJPh}mm<5Hmc zXT*+sE)o4dC_^Nqyj`~V^>Q93xypB@ejn7~PnS>hr#k&F z*>y6A%MPCd#@&J=v#1=m4W;|$KzyK1wfr(~i?3tgKJWLV3u#oj>&Y@+?5YgwzcE+Jg zq&$Na{q+Z@1oaK|2c0iR*O$%t976YkyYjL*M@~nP{QR;~^)<#n6foxqyt3Ph>b$@h zL$U+s&kkd9_OF)@KkJ{@s916Shu=p^UpD73#6CUeFmP;pK0SxyC+qMGh!Zsq@7(es zhTM08c+7Y9;-6`ox}}11IE`}G~`)7OD%c9b-31D5s=Fx+vyktL9ez^Safy#r+U(2(3hettU)c*C!p@diL_M@ zobuT6-D^u%96tOH>K?l!{jxcG%MU;Inu&=&7CSG3$ZXopo25}-zUVC<<-v^Z=NDa4 zUSPj`$^0T5X2HNUbbiNsYC9LDZ9P9Hf6+P&KKg_0sqJhD?cGI~j;219^ImX2W4HCV zWjo4E<6Qyh(Sx7e-yY=+%v9b9UVnRl%}+(0kyd8rOpx%!@v)ZjW@P4PF2K@^JJ42M zW(3xV4Qr&Yc8e?+I1SrsX|VRAo3^GO10nc;oq(P*Ajvr6gJ($Umzn8H$`rwYHEXm* zAAJYeW3mct}t5GBf*TW@Xa1EdiWO%)ILUM+KluV@CIpp za;`lqtGD1&AUJUUR@mJaG`1%+UY#(mCny$@qBMpwzDGR=r6$+#WRA(|;hA7~kfP+t zGh&T(Vy-=LU=Q=8Db_?`o1AH{0{4_aGss*JVw@V13hi(_-Y=vMtfz&&^+=xAl7#fau(+O3W0%r#io zEfzY&%w|-Xnk70MqNQ}i`ycc|$@D_{TuC1Yn-_M$BQ~KhA##DSGLgZ&(8R~2d08kL za9tFNEv$>fYBJ0v;b{7)hFW+Yj-hibj#k0O(*xNh=IsGHcS2ih^#uQvezg^!F`;R5 zqP3;2ZG!#~WBg=1QlQU_KZTBgKgUk1uCHpfl=)P{Qa`8x+4Zf9Z08NT50WjCsK7H2 z&hP9hob7RPtVlE7f^mLtx53THaU)fq%HVt z!uhkIo)~EgzOjtgSkBvqJ}lCVuThF2r@gA$a^A7WpF$xgMVj? zf`f&Y^PasQY2@ULOk2XZyl?X*A}8nMNTRi&rFBVslYTS9IcyyA5PDq$mSk09iGI_<`HP_!MfA%U&WHABNxaes->R^jPwbmT&-sz&IUUJ(vpo6X zd}_R{j8uiFpV>dhY~IPKL^k0o4a@o59w)-qMXIWk4efDKOYo_h^S{RbS&@#FtyR@v z{lYF0)|yB{D8;RHmh(5eQ!=(b(ox>pBA1{zU)t-1u`!Y`G-3U_VNFC5I-i944?|5x zIyAKed9$Ia8hQIqJ0)^DB8lZlY7)iEzl@jjA{{=x$J1AKI@*4fv)zs)RweLBU0nS9 zTl}b;3+zaTCii&x+P(qdsGN)8#ynjTkJqqVSkA*jzqA(}Uv@dR^9OO+gFt$GNI;Im z1W`Fx!3p0{S&nkjkmM@oIy-F!^VxNF2*X}GV%|2P#E7Bpw4kbh5^hau?*1B7yZaf!zx>By}CWxJ2EHI!rf}^8i?Vs<8Jr><`+JX5V3H0zL*f ztez_8VLMV~UOsUKIT-^;djwJ{PysCGSm%49)NjC5fg;chpM#x>W61S7MEbNLM%tU; zljl{OuQ)R1WS6GmVycKTbV0j78RqG`2L?Wy>Evc?y`! zn{w)DwDI6d@8QD7Qw?>^@tW)q`($6}vuykv7j-gerMsTXO!nNxXc98UBiq#o=PFS8 z5O-CM^J7>diN*0`eM?Q7rA9jMqFX?7X=R!gb$#ejx+y9t?r9f6oJvVLuxafmX>7q4 zd8*w>!$6g-YX`rHv(zSMtPs3N$LiLGBv?9})k4W)bxt)`qh45Qv(qZXXryDs=H_Zk zbvl;`Ar|SFi&yhj@H;$pu5-5#heSG0M!%6-ET4*M#mif2oAZK5J{jTTU7eOz9pHAuJ}!c1blMxL`2iuCpk%xi-@`Rj zBe~8u9C=9MzaZhVn4Ep3#j+r=AOGNVvE;!KFlaX>in#S-9qq?5-;Zwxf;9_HnyEZs z5-iMA0jFa;cVfWHDFYOrzUf1Jz8a|5_v*qDQw*MkrLA*m8#C2XgAC1$GcP7qJ{(YuD3lnpR$<@OI|LGv~x0z!9DSHH{ zeWk->`e}EmF>+Uj=gt(rOvfHKh&)rgQAws;k61XR0;gL8Ct`5A6TtCY^Le`G?twky zGdQW!y{CakiQ5DGW>J4ftyIR_a2tpZYOPYYqXUz>SjuwGn=z3kz>2k6?iLZ8gXs?`Vh}j>HVueFARpJ!!2Lrc{}n<$6)IQ3Ap3bBkdqlw3DC{@x?{w%8fTkQLL$d5-qlwjOQ zv%Kbp_tn%BhSiHy1+-_Pp9)`A*!!xssyeh}FGRl-w`ioHrejG8RsKaIAw~*6Ojj>O zwZ20zx{ueaY?+IXrWY8umksyOh`eq(dovYGHDU0ler=qxBY4TJp$YwEO-Tzr$5yXI zb-_YLKg@BbKo24|M_&~RT55C?=xi|@h-S%b0WI|sey6X_GdyUb=d_?`Y%zAU z%ox`3QB<`xI!XMXW!4iPwJo|>C}@}U$lFreqpd!HXFLqLOU zW_4<(A)!U~$NiSNzz|ERc5@BKn@PTTsCGr4kTB+RP^5d9OQL@g(jv5OER$>$`pI9< zc%Y0lj%oYxQd88PRr0?Klq@!Xp37YITvjK~WhQD_Tj+&O{fNPd70Pq#0|w@YFo1eV zKz+cc_9F(Tg8=Z1lH$4D0UNWXADuvbDxh*_R;YR?Bi#+-)sGI~i_6wBpwP&6{FK}p$n0Go@(+xcbLeFryxhCF$8&!e^CQJQ1x&*C5+Rdy0zXw6>NvPN>I>HxF|@FBt#JO2|x=>R(|*AJU2*eOMwXWUN_2&a=EnMbMzY3&zE?;x@Tt3_E zxeVWPT}T&OF1%#4<`>4JQm63)5`J#M6JR6a42#t-)cUV zXe=`60|w2d7ArDY`>|rU+oCA_x|`nH58t46jq@;MP50)rlahpCeTZi{6YY!`k`jYs3`d+v_AuDkODAM*KiMpbpgZM5q?R+qEZ}&i z`jEY6-h&jNv;oEDjcaGQ&3BJ8efv1)*NX36M`{{c(fjBr^(#t`fh<&;IGi zE$6q!!H%?rsIU3+jI=+paJ{a6JB}KAk!Iu9^cl_@hEckBEUCSv_)r`t8yHAPx8nTS zu*7^)vD`o6ylv>{-7&vNHKiJ>FptFIouLo)mmoe=Z;8z8NV87Bj||61O)&C4Hq?`? z0l`AWN}JD5XZrS-bEESJ2r@BpZjyx?<^xBG&dsvwz?MbEkj^c}9>Ho9ro@(WtE|B= z6*@|AtDSS3(>#`OW&e%0W}Vv|J+O?50_;+qRrZS}d|G49HmB)WKltrI@UkRnIp;g2 zBF~L}yY< z^q4ikJY4LowxiG`(^zYqYwZtUkF-_S$D69qXSAHtfP}ivR2VCg+|Ve^r1M>yYha>j zO@}63Z%9KT$<~HCO}oL+#-XrD((N^bq6nT0-YAP_-?P6bYOPHBH7mnD6R}ENY`Tqg zjb0GnZ|j-J>5=LxD7ju5T<1ok;JOH=G|tVop3|IV4d7$RmQ!he!B~o=)H%r=a~$G` z-pd?{#lq|6D zh9YN_t7~>Nl59DL^a>f}id65QDWMK=6kCryxI88}=iPCc2?NSG(VWpZ2mwB#Edn~QbkLx&0 zHa?21jP3NY#-5Di>O(y0ta5iS?V5GERv1<*jpKS}wXve~&M}XzJC%lpd5h(&ch`;w zUrv@aK$nKo?aLu9Q!GQB+3HN30gfc*wzf1`PKna0fxscQCYGv8gF4(|IdhbmacQ2F zAk8%#sKcn#mNU;ZTTxkGwVX2bOOb$SP+Mud7TYCU&|YMk=^>Gntc+u7QENGi4fVK4 zjl6=bsY?v?cvMm}T-fX&?@~iO0dYe&1kskW)^0|GGJSitv(}k%0+UbrrFG7C+0CJS zY$$Jy*Wwm1%Q?d|8;(rL{C3qj(~y-enCp!dC6P_1tT{Pn`OT-SQaM$Qo=&qpkZy5< z!+|Bc4$S_rjN?=r0%ktJ)nZPKlPk$HM7QB_XNp*dS_2l;=pwz&E9~fgPE41#8az>Sb{~IZ|ahm_&)veN=UT8?@MNx(t zIu^9e*_f(AxxdIbq@~qSmy1oDJ+0a$Mm0UI0Qx^M3jNvvo^1)Un{&Sgwdx>nc6xp#VMME3$w zJ(fGoXda6s=2x}zRzGK&;TRH01i?%gF) ziZtswFTIq%`B92SEJPk`TC(}NU<1oTkTP*u63Jc}SYhNz_)3a&!$i zE={*bC@6kEctYAGQnXEd9h&x#SW#aWRk5m`Xb6}u1!e0TdmEI`^zGxEmm@1N;E%{6 zob&65KN(2s!P_f_;7W9V6Es@M*7Zpgn&0|OmFSMNd(~8Y)Cb*bVjKFkh*lFbMqJ-* zGUttm8HMWH`&~r$TdW3E8~nM!?+rCO!n=akH_Cwa&4`JnZl(SZ(dm1#rDi92=Vsa| zRfy1W+F}oGwo$pil>{kD)E*ooVcaedjwPCxHst}}vF61oTo-GlO*J_ht1{wFr8A4d z@thgaoG^kDf6UUEa!Sr>q@VaIa98kh+da|##TXTaIAh{Ea zeLjvo(4J>RE`nO&aLNHWl1ShPE<-J=NM4%bjeG5oIeQsH40S80QnJ z&smA-m+LRY)bw&HjVExd!<}jb)%S9=+*9p0MP6ehfxV~G3|At8-r1dIY{^KfxnW~U z&g;0-^|Dh=2hT>ev=-}CaCe5`J&$v3Y_;n7wwo_xIVIB?Po`R%MP17+u>Xu;<(Q17 z8#N0J|6w~V0|nZhY3v{3Ku0HrCAuP7?kvdym2*TNc5#bj=C5*a#v=i?RAX`l+9S7E z(plwvX-DE6iAJu_xwB;otaAQkN3dpxTlR4bX({L>hW-_T+JMz141e5GL;JV*#|jl_ za}4ckJJQt9EXN+W-95LZ6`MDfJJ&dGcaRblXnOS73(K8n9B`(9=dj%QCTbU8We)A9 zzCG7nAg8zVp%gX&a{A0&Xn6Nv7@+I6TV{8%#^&IZO7n`1s5pxZ&l66hQwWPqnmps6 z!HeTO3DO?N)cCNEyUZ{@?^uI*VMcn+bExFU5{8> zm81O^*H2{a^(@6=oj#I#r9<8H$=`v16C14bDdayfVWrEG>WQ6J`l)P`PfRSpYG(Rr z!iN092s?cmw`p-a7P?Glpu@OtnLdO2mczbB4fDBPFzjPe3s|Z7o}!gr$X<5Xmt>fE z7pQ2-crFf`#F#63E}JgT_(z>lg%%*&@$3 zn!`P^xGya(G)bTTLoo1JbjwX&a%rH{QlpfFRc>^OF|1|U0+kTfa&1x8U`j||xex+8 zmkVQ_j4k~=gatUrC-bB%=OddZzakB#m>7L5rGazj=J=+SGOPQmA-Qrk%5siK>19@* z8%-_H`9B|o*Ne*JWA!o~A- znoD-!m@~o(h8u-}$Lx+~;ISMqJO(EnIuFKuV^|WPiOAbvKb{dD0dDDCZA6UA0J8H0 zfpj>Y^B|6lgoD9wrBDaMb=pucJ*R_=LJQ&Uxm+3cWU;_=Ig|8Uj^uD23`;HJM4^-sP(sMrpDT`YN z{u(|OHXE@J`#ZH6%V;v@!8zPuxyfIMd(#B!>V>#J7%OHUT%?cVa!I*jONN!yCquBL0?$(6ek~Ojl=LdSaS;RDRu(fhLk287hSIBhLa@Lt; zQbb+Psn0Nkj7Uujo{n+OGMI!jD8jo$4 z*$v4iIlp|q%gW?WI<=^A&NVKFvyo1&d2QgO`_8q#KrR2eAOfAmjSW>80e{y}uuO~5 zt>s*A);zQHoZtqtBq}TXEeURuux;3Dq7;jqjn!1WW$`^j8x(2q*EjbW{W-VC2)x^* zCPvb$+GO&-Ulhi17z|??+00nZjqVMIDOPw9XRZexe-7zfQ1C3G%cUm@jxmdyjb)5&r#nM8^X{M}C}nQG zK9udrwxd3m;1*~a&II9ZdyXIqe+fNsBqG+@vZ6g>6JmTQ0yK?y04egd_>abXiS+wPi z`bms0OSQvEI1Xf3=V(ecD0*4IovSIsV;frPQXuNZGk2cut473{MAk|@Cv@lQ=#PwX zPsUxKw`9h}nq{5UU8s{UFQ(7>xn+9NHYL`;)dF{s_B<_yB?%MEV!aGlG>DzPyM&#- zlT$i~>vHZ=Ep2`b_wbg;cCuTpB`g}m%M;yYJlo*ptQ^D>NbYjI>{c18=I#fFM=6|- zTBC)mizTWyH?~yO$YD|UbWJ@gRwdhA?%L5(3Tk3iW^uw@rz!QZD#?*Ew4RM9WDQc( zHlhM5zYwi|4P{`c=Wga{E)132PU?ALf-BwbxooO*A5jlyDY7S712N>1MDyH-Iqr(- zG1$-aZnY)n#o{<_>;7Et>|vHi-*@;D@C+t`u-wBx0)^Yu))4oD{uqYGnpZToAaDLh zM-c^EALe!cq6u!SL5};nA8NZdh$lDQkLVX`cd;t%{o}!6k0Qbh^LR#xlND1Bm7c)- z4SUztK*6)zFWX>=HP690U1av({qPf}{QpCT;KuYKfcsBv_qb)LAIovm?VS*TJyUHT z;(9Wply4;54D%_3rAOR-%$Nq7e_EGJGnvYQ%8w#HJeLDYj8P!cbH^bPI7JCu8jnwb zNK}Sc!yB4$Jg}h#ZJW-|wxwL;X{c?8*T_t}&9ZAFwp}zC!vIX2Vd1zVr@^x8WbJTd zPQtPqBCHD*E{ASt!`x(Z`4r2pa%9kM510a<3A9U~aE3ghlangiSU*O{6pJ>dSWYK> zZV;Ez&m%~NQ>&fM_OUUnEq0y5>N0W+2h{dC4tw~KIn9>cB;3$t^dI40JMR={YxF0S zDCN?=Saw0I(F)p)`55f>cO9k}B;wDqZ*w>r$72q*IYlX7dB`NIe3E7FvTb{%M2t8a z<5TXWBD*ACMj%Oj+`=4Ozwbo}D{vsYs*%-h5jOqoMd`wC-v&{q>|wZz(pk4gj;)fa zYL}<~7*1JM=p#quAzLTXB@Z*LEPC&yC}xZ$qAPOmJ9o7YW~DACbzG}{;s)c8;?~xx&6fR^ zV`sx*2~0Iin|LFcse1z`c-9^^2K^#zR&HyYTeVnK(f*rk3celYuQ0E``ver0CMNM@ zXgvYGo9KBNEP2=f++^9!k!bMgh@XY7d)JT z^6(Wb0I*E~7~>Gd@>Bblg9mvt&M9YswM2dqEz z$UuIqz{J)*)lR@Ki|h^Xe=YsP%c=AN?^8R0bL{POxl>U(PGuyVF0V%)K3rqjvurZ$ zhm^ZvUV)@viKG?DrX*Zxfi%SYp+5L-u$La2Fow40+B_XI2mUe@j@q6^Es8<*)kw?^ zEbggE*423&VW_S>Tk;Ys#ZK0x@O)~g*ypnEBj(S(q8*m~ zXQSt-Xvg0s9_ez^vb!y;%=Oe0bU}Q52}#gu*>h~sZ$E_I39}D=eh9(SQ6}c-#aa~d zUfw0?WL@4~qCMXWkM}d_;JI#w_PoURJe^Cs;53>|=Q1v=@#c@!e$Wg!!iQG$l}@v zRtZDV*Zm8MQ>Se|f}lQxxfFh$F{*d^s?QYVIs?_E!||=2HIbd}5qKVocs~IFUqHaD zi6Ek3n3XTkoi$IO_l-KBeqL_d+3>yy=3fx82ouA#x3_W&Q%#Ba++4M9v+eB=@dFsXXPZ`_mAlOsqZ8;h zU%4VC$hX0aD#XevagVUU$_kRhB+pT03g6qXSgdj+1Mh{1mtk%}m`hBUs~l6zb(pK9 zZ$lH_TXoFv+RWz1!;XCjGF&9;=a6%&k@K)GXF3Yl!@iUPne^H}6Z<$1>h~)0y0rhz zk%*Q<;t{m@d@c9$LY*RC`ceznQ~kqXSG5!FEXDs6p|{Y6MRHqjtM*0TGUH<=(^t}G zZ-RX?`(%`4B*Y-aLEIGxrHEs~C5S*hnNL&2HL(9L947ApVbXTkDl;vsxE06;KxRJ( z@_wi_sSA|MEFd=k*+=A7AkP4q{1UzX5VkjIJ3`wpV8g8p{FUTGSH5HM6N-5o4!LwF z;gc40dV%DZL7q+WY!BVsTO_&2eVz}uCbR#Z^aVIlS|TnezyO3t1j;8>@XZ^>PoujG{adtMKnQ@Dow`kIcAr~PM2MtoSK$+ zTd;f`9Ll#n?Gd}Yfula>Z)b?h$T9Cje>+nuhKzJa2pz;;Z3x?UPH`|4yF%G44gW+; zyI~H`(k0?bWyB(kn$>?s(bZv9A{U+wd{n-)XY1F+5q*u`_M9AM9%lFF9xi)s4-Z2tqB z{`E>Ro{BVcS^E=ZTL|tVn16$NZIMp0Pl6;%;1vjPaax5co}UlK3YZz3lG|S?&dIsr zGGi_Rvj43(E3bmVNV%Hdj9?4UOta>6RAW1fdrtU*97|RxR>!zDUpxO2CJ8@}Bk=Jk zg2%Ybue(5DosG)6(sQs)<_NGLQDWHxWt#W74yOcfPB!CtLVE-rq<}j2z#KaO;}Roo zgos-L3dQA!xJKA|7bA>V@o^AVGND(#Yu^hY-$H_11IC(SohbPt2w63g`&-~L{pbwd zWMvn~1oQ<4gVIqbjvq3ZUd)R0QjanCbUWu7F zZFJdivdXtg;5p_PuHB}sY(MpqWe&fYs;oAGQsO-N?Ah?lRU`WnSEkCN&kHEG8p?M9 z%6*!GsWmT#upf2#X{5-N4}I*%beNrsah?DtQ|!lOAu|W|hGzL*)qX66BcKMi(k_7Kbw_8}TMWPC>?6tS#xVS7H@Kr0@E;;<0hledE~ zDI2!m!#3$#KrY7y%cSW*o+eTXWX^Hu1z&>uyD-0j3X@tuy#!QryAFn12yD{jAngTd z(q15kh#Ua2=6K7R`!gW+>Paus0rp9M0x};f&?O_0S;a6XQ@}K2{L`RXCHEp=20n}A zZ-M+fl4l=wa6vdppTYk}Bu(Z7W|9YvRj8bkPo`}UY!|SqLePH1_+^-j>FW&mIzWf~ zlOTICBX>SXk7!QucLKJvsozr3iD4$8G^=}Bi+I@Q!slMXz`Afnl$NukHFL0NXyA5TGm;{<09Xq zl<382Y&tf@erY@K5 z_YcJKJ9x99%w?l^!mzJ%}+l7(a#?I}GFSdB|*T6~loI z>*Jt}=bZXM`E+0~_8jtgIrFbzW{65p+El3w4oAgFuR1Xd%dwAue-hI3Oz^#nFqo#6 zKOCJeGZ;%opa;P)U6%eVeO|Q78;?#yJN_Mxdgy7(`r(9ZsB;KqYZOG!V3o6vleNIb zaG1fhbNhIax(W7zWB{DY75kVz;rya z81W-*(X;IzYl~it_=&ber%I$A)csLxfu!+IwcC(|k^piH;UntRtBC4!T-maug`xf) zlO1UFM;L23$|*EsTK>NGWXD_>gmE1DJ#Co=?)>k<+wWj>BK|?+@4(sqoqHU#@WGNM0&4|J~&8jU!&{IA^4ez zf;MCX+FcXIH9;6`7q68-l5p=`|MURL?DE)$w74RO`W4I_VE@X9JCvq}X_&sC*(ty{ zAIlITG%bgAgrTjYVLd94o`qV=9-VHpYkUdfe}uw#I=HV~2<<0_>ByCREUF z**8giaz??1=-w<0Yhf#5-1%eH=nO@9jCEzfb>o&dO^^GyZ+}yH%rDL`qV!Ry8 zZQ*_CB0pv?q|2F78qq7^?Z9O)Q{b9| zvFFD+E|^~ZRfJiS55X^8{ua1=sa<*(+vV|UeDI0^raVY)&(RaUC{$jEfG&eMeF@aY z{;2+L!=CHOb{KO78;DpGnkQ;O`|13+QwTgqfwd~(z_QbP!;vK%LeL!1Mbc0%^kk2* z3v)DhFY{QeUq;9UHQ?3OMPrytH63tYB<{Bw0ys3`SQNCfw$AxAt>9TKJWkiT0-=CO zQ_ckwGkb|>bOUUFoe-8^oa=4vSd~Z$d_#?4lUfd#4~D zq$pkq$NVo)l5G^KUd2&L?%i-HqL*4v*ndv;BVe_Vq`laWD!upsRCd2*59k_Q5X#|a zFU$uJ@*WEU)5Ef_@n}I+*C~!x(Ij}|qS-crzRpoDZ)H69 zL&(hHE>f>H+E>f6Z`C^Ohq!Bz{d2x$S$|jxop^A7u5xSu1+$gA{v`1D8w%!(_o>ru z9^11g;YsrNcFE&6Xq7U85sfI_cPt8pMB)cxA5VKNQqR6a?2BP9!^GrHlfQenm7y*1 zZLe>Y7>|K^*D=OF(RpwdJmpUS@ids;(LOq^NZ+6~K4T&bPwNnsZIE(ZxkT8qpY=>P zBDD+?C5ew;4Qba|)sXR82`|G}!m98P6Dz?oVE?mUU;N7^Bny??z=#CE zB)uxtk&Cti`wX&lj+1-2^|XRTucgC^A6Wx8tgF>)t_?hks!?)i3>~OLKk9B}*WEbo zVRg5YJA8cEgbV(>S?xM^&z`)(>WR;$3Jc4;8`Z}d-he$by}CND>xRYCXH9QZKTds` zoOz%W9FJg^Jc1K^1b+) z!u*NjChYW{RsFo&H`G~PwmR8+r=Z@e+utbv=lJ;DcY8w?s;XL*ovY3&_)KLd)d727 z&e+_BvhfE_DpYSSmniDTQF0du%{>= zX^YH2xVLP@C%tN5!5X#E%T?nM=D;251AEUNHK;%}6{vo>o7IGcr)}PlN_DrVx>G6D zXP?^Jd2rVBSd}bzOl95Tx`$Ig+dRFnebJ2%b=Sprez_+v^?K{G zh0k_P8+rYDmGSA_YhHV(`?I#P_&vY4EY*HeYEAdE*X=pm8<@&pySnbR{KB%+zcak9 zaQYdl@2jI$?6~>@@7Z16h*V))*F?4H8TCEKduLCf8kAet-acM++k4deTX)=FmtTl% z9r%v-?&+&`ww0^Sq&gP+6G`gj9U z9plbDrF*kFvh^S+;l zVB0~mcB_3`ydB;76I7oa&d7m<-pt>oR;r9WUhE3h?=CgW8D&qLKI`4RA9g+KrSd22 z@&&Z3bD$kU;uE^gSHHAhMHJLe5$H44!RLOe z-mngKtM-G?zIJt?y0T-3SLf|K@R@qwK3H)z)El-(o%88y>Z&aV)d`gJodOdJguVZh6P+N|jyqsQQs}P~EWw#q$kkpW40E8{iFmO*I#&QC@AT z>?i847BuYIR#2|`yy_KRp|b9JEmh{7sD8ioRrR#>jyisy8tc94jZh^JG2DAcJ??mw zh209(D5FwsDwsL7xx3rj$%;Qb|GEr%G3!vR6JJ=a0*c6a@D46)mhp7>;aWka9UT9YFyZbnxV!n-1Bp9>V{Lv?ENL8Qy4>exN%?A$_iY^_Qh^pL4#bzQ3q z%a)aGQtkT=sA;c`Iwe_n*LJ__O;7{T1QxEV zA9nf)#V1Tgdz9OiU)WYS3C|&Ze_JJ5)>?JTwp_NbWo4~J>e$>*R7>u_ zb?go`$jjZ+1&@_zUfX6~*{JT=wnIIEk2>v#RDbA|jiy}P4OuT+wG+@j)^^8ds^_gr z^^T0j~up@B6%+v^)Vzajo}R{NV~Ut3b`Gb#nT@H*QkREH$-Kt*>=X?e9z- zbY@|^LG}Aoo&D*~CUqK0&VYj}u85yr?_J=%UO2uB&0x0LzV#h-y;FIiSBQ3Q-G;NB z(F31-R&CtTgqn70e1dAry;g1Z3e@0tRP!_5YwG7@&RuXU z%-{d;_$yS^KJRsv<-LQV6x-pI)lE`0&!|6bK|%bs^XYpPGsm5-rsH0fWD%NXb>EhP z3)S;Zt$JWf0bnHvx#~ryfDVAU%@3%KfB}mZ`E1*!$>@Uf9F8NR=-hG5KAx1Y&-1cemzzQ(+2fmEHehi- zZZ)8cIC&5viS(+PN0OU!GRpghA|6Ca1EA1PZz021m{P%*Fqn4xi&&iD@dide)>zob!i$naSJJka4 zQj5on2ijIP-1y^G7{*zFT=1>PjV>2HE+_G~A3Xg4{jf_-T=K*fBR;ra9dciw;{rKO zYmah>41T^J9_vYj{770k^ZWQoRh+r@@sg*CnY@9nkH8PtjD08q#kn0PaiI0g!Ni&(#Ln-5BJQFtp7+q zxMN>2(8rVo=hoclCJ9lOhWVKbaxGsbPk*p1`DsyqRG2*6@qcp9j{Kk9c?M&6Nd6f{ zel}?QZHGH%qCxn@J5}}LrjYw(kcS}x8K@6srrs=)T*cuNk%S!u@X?RNWnSONS`!wg zE%M{Bh5d++A6Jt;=Y-OxIMaC_#qFBh>~*=(X~rKnw|Ro?D1S~%$m5($=PY>qeXiw{ z!HGXB67r5`&uglIEK^Z8@wdQA*`UMuee%Z4m*-|LLBa-kjqMPqAEaxU$!kB|xn1&E z$X(JM0-JKPPtUd12Z>*txd_6Ga*nTsWs;u}Y4;GgRgzJEVm+j66|p>!>V@1F2cY8GZX zOcKj)Yl@IKg&{rA2CvM`Mgy~miG$`EZJJ-FwuAS~5U*}GD=1%5a*@&P5cvK##OLd_ zCO5hy*FxHzE&tWMHA8t05sFbD{IunAd^lX_SSQK!_-r&w(WQMJXUfdaEHdG9z5TNP z41ZZjd`Tu6-mQi}-^H18nJhuNa6$cDUk2KbIqXlji3i4Y4$G^bE?fZ*x9Lkoxw)C8 z6b!yR82-4xeIMXac{V@SbLNC}o0qvPH@ZiBpzX;t1p5;q4Ag&p4@UNU-t z-FN58);F~|zB^Z~vP1sYNlohU&jl%TC4qdu{|1T6N?4If;wTOJaE*I}JZs}vDUT4x z3517`Wt4QnY{8T0*?N9xQXsS3Cu9Q|4#OY_M`_$6Tr7CXBV3~Cfv9ZQC&EA!!DK-z z2xe$1!8}dHzx=ZC&o14zmJ`sQvRb!w1Imv|ErX#hgex@e5#AI_p zZ#3?NZ5sCo_X?i!2>Gc2WA6Lg5BrUVMtHNvJ;K`sPkDs=upsP@Q-J#njqrYrdxWKE zI+==u{HTEb2o3HBZT&BJUC<*I&)s@N$)c@+hMYJogP|0{6&m*ly9G~qg!?t!CH#e< z6Fy?-ez0p{uYu9QWD(s5V_Ovj^o=q`aEqYJ2@VR%p@#f6!n#*TEWq+(D38KWOF};G z2;3w5o!}{tkY5y#htS|1zKlbly=B}9-`2QC_%Fdz9w9#{pbSET2Qt_u*)Vh`R2ugP zhY6nY2>A&Cc?b<2$jAn5xN#@U(YQyrOz;$zSaGmN(_KP-Fu*+b<1!ZZd>Ea|Lx^(E z9jQz}A1Fqc-Yz(b zG9bSl2>avK@_mLzc)!LyLhd9nT7;aD&>tZ`AqYqJQ}FV008^;^F9RH_tI}6*6rA&5 z&=hq7@WX*ntCSDx1|co?Jy6IHc8IJTT8 zeqv~ZpK079JRzcEMaT~Y!v3;hA8u%bIU4r}%LGq(g#0=n?2q%xWrjw$LgOA`LhzJF zxKY!gh5l`a{d_|s+^KPo@cV+NJVGA$4~NG&=zWGp_#=&bgpUZG@(3T*beHf~hEDjh zq5FCqg8eN+BRs5ek5HxQ^djWp{jeTK;QlWdG$y_%PHUGLHo_Ge_XsZ%JmnEytm!Tx zr?laMRtws87{xY|h-T>Whj7+ypnV?(;SyNsf?kzjS^Htwv;o`-qpXeFx`{jl(?^=% zL|VqzBf9?$`!ECxUV9*G)~k5fX92pTH=~tLY|k1LVPqm&nnLs}u7QAO!zK>Z;TD8V#A%L(FwF5d;fM_^p5^$AOY&p?}m@dd%P zFv@CQ*G*&wLP|&dOv`w4L^mx=BXK1{JrD@N-vwPxz@&jJg5xBGDhQZDpq2ov(Nu!< zFj@;@yR`#Bw>Y#zJz{sm1Zq4E%b&soTK)_pdJ$pTAS^!<{(145W(nVWstZP41!6Agz;05EnH6!6(PBmA-R=)JmB;F zAc&yFXAo;);7Y&x(+6Q?sO-fM(0h12VW3ur+8K49|hM_b< zreYfKv>dye_^)BWM!-Z3H7`_2>yg*p4{`^K>=k~Nga)XK!C4K%MD`;@pP#^>oD2&T zTg?z(lwgALZ~#pA3u8Hfj@NQBJ}Znt+02J4Lkfp75%$S2wzZ6aEMeysguERlOk)z& zz`zRuS?J8jGv`3|qrgo11cuEp;b$862+zT^l{~b!WeWi>naqsdP0iVbs zZ(7!(PDcVLv& zwym4U0>}k@JHW*-G9e^#iO`o3FlfYwp}q-&B1rHSOgIo|yX>j?Q3 z7#06FAf*xyM~Fcj9ih$Or93^%IZV&A!DC zAv6^09Y8k2GC3UdYzbeHf#Lnq`nRN)a4Kb0zj2?bjmkb+i(YwKMw^htQ7#y!Hn37+x@`H@suI{oc~ zfpmiZ6*QE+y_J1g!gOQ zBRmD|JDWE`ey$Y`|4X=^2pYmCpmQiI{zNH4T1}7+gIcw%n@E36C!kNz?QS9?G~HK> z+Yl3B7$_lMzX9$M-XVC(BfMABT|$276>g6y<5Hn@MehvUyMXE61;A*7=8qWXP$Zf_ zx>;OT_?|=E;7f3M8HV~1zM^rD(Cx4FAdCo}bP4%k9Q7ki2#$UPke`c$_5LGdd;%k_ zIgzhm(1cS)ISf#OT`*vIcv}->?1lk-KRzA09VXP^PXgO=7#4;z0Bc~-b+iLe0?}LVJP*I=Dr?8X!{(ov=Og8~=MPYT$?J)Ba0} zt%G!(Vyk;nY;`!9d_m!K_I)u4d~d|R$={1m^i>!XJ!V2CQY%ynp8$#9J%&g;&Ts2H zCZJ5nUc~R1&X(-zT67=a7chvFGZ=?EVSug!sMY8ufNNmraVd&lJq$PqE|SvNwdfAO zpJ_6|bB0XFbPc7~c~EGt$>d)HenJJU)h}R$l?pPoGXV#~pawk#y`B`^R`dI^4>cNr zGBHsoubay4fB`dgJYdNDMC`Ykd@K~;$7B>e8<0^zo)fG!WJcpEA+PXN4reJ#vwMPE#}-}pE?w)`J~7+KA4=zSp>$s7heH`m z=RVfHVA2#y?|Zi~F033#uzRN8+MrROKm{3)0a zDU=wMp~R>RB}OIl%A|i~C^0HSiBTC!jLJ}ARQlSSfP^?1CS8vzb6i?Bz=YcJP(wWv zE_21ToPggkV=l(rY?CN0^X1-w47&#=G(jGX7*6UPOaJRx%>ORHc7p!-#89v-DsRDX ztVH;>#y!H11y6Z|f7SG08JEX9J~1@H&ou54*5ddE$4rEEf+t-qgwL#F{VF$F3Z|F9dITL>X+|KCz3NU z?w>poT8zl?0zMG81w`KmkD4rlVIYJnH0}{r3!d@_Yc$;@yxGtR`FSn<624&QgfAI7 z;U5g0kRNH2pYS6?C*&u+;fPYNGhk5A2{yneE78`?@Ne=h4D=4)@*xOeLo>apL7KNK7paSgr8~LBfJ{N?U;9j*9e|;32!rW!g~#! zkY5>xix6dJi+h(#m;-|(poseonebtlZ(75k_jb*fMYtIT-U+@V=xR#RfpVQe|3(MS z6%gbCGn-`T7(k@HmHSV5qfSNN*)tkhdDq9@?n8utkM z;Y<_5C5#H5bO}#3bizDCC*&v4VLd5(fY9=~2~UJUmYf1G-H-|CEtFF{ja4kpC;)&Z z8utj#5Ip4(o~7w7;g1cS@F#{&$gilw8m)x=OrdqHyCQJ!TIZ+6Hqb7FfjR^?30gr( zk7<;ELPPq#1nbK%OhLlmYTP3{;UpbCVYc8&mylmehxK|7ycwXOl^F^!R->l_G-%XU z@GCH;fn@fki5@E)K|!AnD?O%J%dd2o={JlRoNxCfJp$UJFjSlHagBR~zZN{@5x%bJ zF5#PoPRLKV>DQNc2==!Ojqq)adxX=ob#w`f1W&qzU50L%-#@`S5HzIj41lE?-34%& zMlJIj3Tw6|5#$M4u@InI(A5NSLCXmmHA+Bfs4Nu7;6oYN7uJ(u{FE9CoRWR}Zs7Fh z+b#3+l|g6Ja{!6LOjLZn{UF^4!&D=@S>qnz9|T7e1b9f(UBZdOb;=P=5jD$a);6hw@9HQi8TkXOgrj;F80B#+&830?V)GQ?0n-vH-aAZ zCL1Dg%hs^a7z9x$;cytF0p(MFl5aD~2QpLfEf}CI2}cLW5H1yAT`R8#4!_!Uuo9zHvm7E+Da<;h1QkeXa#t1 zcA2CwM(=Rr$|JPK z7=M5UKaX&e&{G~^hu}$<@H>W1xW~{5`MrL)&OZv-n$~p|B+KtJ(9*z%R3u0Vx`Kd` zLA@M+oEqcAq4O3A`Y1-^YG9-6+mz z`vGs(xJUR;!BZaLzck$?{9D4L3am_ZssKonT{p?=B}0Bf zH$=`W>E$993%)U@7ftSF3tjCtWbS`D%QbDG5PILkHf3HfA11Y@$OUF0Pm*m@Ko#fJ(kUV$^UAn>xRzi-{{Sd7t-j-}lRVQ2ULMSdqlCvN_e><+9wW_ju1T^sBZA7!S zMQ%+F^R2JeZ%=+3M|FI9Q%g+>@xSIjN$*B`xU^8{21RgBY0_HX|7b_tj}>p-u-V%8 zA1*!K)~DL4>f%<@H>*1;M3!hZg_I(}*FR$b?mWbuFxG_znbU|jus(ogeSOjz&yZsUshM(Yuc^KElJzQ&t#24hT$XMLKgEWWMAce|`H$7w_w;2p5Yo5Xx7 zkWYBkZ?*aF)^akYFF9`zOt)fIr%#p#AN4~YeCbtKL$v2WV}EY(twSP=ipA@` z_|Dl60ZGIy4{(_=LqrwB)%lz653RoKFrJ^lh|O%s}2j>R)%tH#(V5lEW8-8Y;i> z;=4&(N)D*<@~+W-B(^6|_q56w~@Ps#ef{h;&sF^}nz&hx?K^M6OX`}D7& z!yx$e59j*yBcRjGKZ#3OYC((f5PjKh3!S{`}wHLC1?nRsl?y zes4dd6$}sU{RQR;m_soBFWMi6E(YjhTHL<$fBqRIZrpOymOI-#-{k-9grEChj=<3E zARrI-_&>Jx^vjK1%H_cf9?9_!>~Qm%XQTYz(ft152Kp;I${!E^_`m`%=Iu_FuEFMH_RRw|F;7;`HrS@m4u5Y{^E|$pWv$jRc^)O^IBU{iP@X2mPB<+P25Vb1Mxk`7?`6s8MHNH z(r3EnqX!fnr5yIQYz}BFvp5jekxNXGL9ryM>9m^lgu}vx`timZ3{?z0 zh?(C5TL}a%>0QO=U-iqVq%~R%My)EoXA~X^`Vk3_NE4>N#hYdwNvo>1wgE33Z?>9C z;*E_MLs$tj0_5GVGJKm?QZgg^|Oj<3ifyWuMun_I=s^b+YM~3U@rk%C)l3??Bf9A?Zan?D<8Z%Q?LZOi1mW~ z0vP+FH0y}~dnUl153rX4j58zc3e zrX?qUX}|3NHRAd*IzpYM%g`0B6xv^b={)))x>!v+9-UxZT*m{e73@r4+O2yv3YZKbefc8gVIvyVZON#69=r~h?O#;>~7$0NUB-rV|Is~f*wo)(OtFeadib_%T&*tvq013OQ!bAV|n7XaHLw8w#IDgOg(lhFPJ zOly!n#Mj_7U|Mnl*jC}Y8kqL6FW|c`zd z;_+@kYr>pJmx%4abX)f|upR#&b8j9WWp%cXKieb^WFP|!7%@N~pr{xKi|iT*VH0FX zNWcXlWPw0PVrB*+f}kPlFr_b8ZEb7Swzk#Qw!Xe<-5Y@yq^oO%Ditl&L8xC^DcZW^ zcirbc&pk64?C1A>|9QU;OrGmp=RW&+&b}zQ{`ub5T{_6KWx1fRpsxwKU(g0LdD@jN z&jW2&=(j_>c*!mBP&p8nAe(`fD!D(4ZbHyWL8kGS2pp}Bcg0=&(i9JBK zEBihGiYb(HfoDsBpm9KKVhzx3O76db*z8|`*zDMmp6(4&{yimWlm&Ar#!zz2z+bkn zOwc?a6erOA0sanC=z7ybKNfTcYCqPE`8;%&pjQRGp6%(rBj|lW9|GlT8OkQsy+hDxL48m%uK|dVlasMUg6+s^h@{RZ8rU}|2C?P0!f>(<66Lby`J`t3n zqXf+s-T8v96y24Angn%-TujhT(Y;sDPXs+9=y!tt1jMEMyMo>m-H!x)0#u;SN_hI245%ieoCWJdF=#=PQGSTxv7>IqaQP7Q|`x`-T3i?#! zx&+yiJo`$3*uGhU=8Ene!hK!Pw?y}}aGwbJOmxqk?71-&h~2ncP^swNDcs$H?h)OW zg?nAlVbSe1#mkdrSOTFl>71ShhKNapj1wAghzXoDk{v^8Z0&&=ePV;;)LePak z?1RgJ*ldI7t`~H@$lWjKm!i8@&;ikXU(i1UInzDYdH}I&LE+8?VxL|p+*lxv`%6W4 zrs&QQE+pJlg02(Yb;3miZ4q>f$i;=*CEPcK`z{dsS$U6kZ zMEBc*9uo93paO$xq348q35acZP0%6H{Xozsg3g`cnHVH!C=iEeA`tt2wxGqLyF$=* zAa?h5L0=KwP9V1BkZ|t{Iw`sz3s+t0*;gm10f>DS6Z8#14++{Q=paymK{0e#xOair zr|$_mBf4FJe6u{WLxI@c$$~By-E!ep30fn%+kn`$?ZWL6xx0kBSGXSudPLAuf}RIr z`}PR>z39FU#NmBcxD$d-3v$Z55cLw&7l>^hAgEAuFBI+)K~qGx1c=>TC|reb*9uoH z+*;vUf!N&*g4#tlCfrUzUl-l)3-=>I|0TN53i_Amej&)3?Zv@3AojsTK~qKd8bMn{ zw_VU}qPq)-^Z1j(JtuN62zo_yKM?LiL4OzBPl4FJtT~=f`wJQf#C{$us1S%v6p7rG zqFXMgN^~26*u+NR?iBQZpof6iwVw)l6o}0}Cvtm)`>k+q3o_<mqkp&~eet#y|+$mm??_i2YI|Xq@Oy6f{S4*9q4w zC@i{P6ZEv`J}+pG=pF*%uO}hg$ASjU_k223&ocbU_OQEfu*sL2H3}sxq-j z&`#04Tey1!-7mWT3B*2qR&?JH^cO+Lf!Ke2uJHUjXuB zdMe+yiQIP4jR|+B$UP(ImxA^JvAb^qar}KC=$}CBgI)_fxqd+G?m2=c0I^)Fa2o_| z0@7{(u^Xp_vln{0K|vz~%@?#x&~hNQWsPtf1$6?kUk(fRcR`;5vG2P?F850D0TAov z2`Us+Bxo!UyKxy1hpkj}=LjknbfciHg4%)D>`#F>M4h6$4~X4(P0-t-o4d&KX+J^d z0I_{DfY`nT!d)Y1y`WZ++ala8!tE69Q6P?&CxF;jdqnqu=>A&J9|X}#e>Up~a)H>V zR|2t5uM%#JpiQFNA>4O>*uL)y`hn=aCEQU#$3(Yav1fL;ppiiAm$`!KM7KfEdePlt zc(#za0r+L9Wk>9*65-Iu&^~Pxu0^?gliLSvv3az_poq> zgnLUkzfar%VmE4qTO-_d;b@sM%XJF3PdGZZmh;PL;l^Zn+;|{1+a}y*;T{llE&oaLL*KJlAt0ABf#}Shz=oJ1X2U;Q~E8 zvq2y>yHYqhgpxU$%jdXyR=7jLy(Qcy!hI%O9<0#cB@o+(2r@9WfimK3C?MZ-ky^9@ zC7v(3Fo$n$z?w$B1e00*yF)ARQ7Rj;dkUxkza;Z0R4DXPm=~aWB#k)<)vn&2%!<;+ zy6UEA3msp__N=JK1)8|xJv7i`U_c#mPaA$%rYJ&-Sok5vHfgElFEqoiqT1?6wPx_~ zLMBaHDT-Ew!ybzd?W{7SKTw;+hXR?2^vZZfY8hm7$j}xfDwooq@mhvb#5S)+9?A4n ziKdVZAw#DDuT8fEs)bqx7CU>-?hc7o~DsRW4Udw88nV}1dqK&KMRP^}e8W8ML?EsZ$?=8-gp?ie|m#?UGL zA!N&BY>Wm&3y70U85l~MBy%koIxsTHgu&1$i%Dh&7&;p<${p_cTR6oq* zXE0+jn3)+&Wd_rb!O*GY-otL)mB#!Gs-oJuRngTes#mRQt=r(K)TTPE)7a2d=kfKe z)$2vk*j(fBEzwm?&$c zXxD}7u&kQ*V}S@aY{KR$t!!w*#=-_P(du~Nb9hk`mWnsjH`LXtRo3C6n#Sg)x}q`0 z3V?7O)}d>`vbLJKmdFgav!RaGsE3Ue)fKS1Xu^as6TEQzZ^w#WflaHqOL^xxZ7gqy z)Quwwdr>Q{Z!|ng?K$@pN}o2IrxJR%c?N~pNwHQ*6=zao)2QSQ^Hj5G+sjim5bLtH zJe60DsXcM2EU#+ErD10w)4ic3$DK`bLK-PM$y4p*ZRDv;au0bbo8iOc?(tNyl&#~b zG!p8{=z1)(M&XxdAx7v-nYYR7mg(S5skhF+Sj=^MpUWp!MQPZL)OkWR6j-XET7 zf!-XRO3BXfRFXfjh0Po4BF$-zC3k**2~FFyQ*B}cv>QB=rLEwpZ2CU%RGrjK;Ai90 ztV!SgohnZ0rT2cP(rFvNJ&iBj_3a7J2Z}wPo>CQnq9RR{c`DyvhlVFKYgKt&bt9F# z9-|7mdEt3YOHigJbC;sA7p5gy-ieV}s}?FduC8lMCeEx?6_M5}XQ2b_*(`1?YNcE) zJb7)A+U=tiWmR>}x(eE&?z!lZh%e#TG4v)I;N=uqsx2yR zz_wSeLpE-$u7L>l<~GzMeYYr_ z7O+KOl?Z9+zbM?T6iA7t&>Ga$i_l!~-0QBlWMeYRQ8bpS*cEYBdVcTzt$C3!s{tWP ziDku;zh^ast5-GF)rx&pbm#!*IN^{Vn^W=$Nu-5u#rm^+Vcm){<)YdEwRn$DXfS%%U zmlltkG;!RelL`vPk0plxUOIj}DGJ6;ymazJg;w@lVA5C!?K8%yj0!ns>gX3yW6%bl zg=XR-S1SPn3o(rX{8C52SSRyu3CX35f@MlDvkkA&f0*0@f4!uGaMRS^KitZmZMQ8B{u;J zEK{BW^tlQ#lbH69yO&;?Mzup#it)N4#4$bM?xb{g=fJ-Gkek$9ZgP5f3t&gDW!MI+ z<=`ayueca%Uz5*+fR{in?NRYJ7V9dL4~=HMeipgZ5i^nw;`eQx2gEe&tBn0+X;nr0 z$^6*fc$piI`eV_f@f(9X$GcO*&epPcI1q~-d)|SO_ASSZ$guLo@hjYTh2MNJRNhs2 zw0&P7w!i%oCo(cNCm1g~7Hf&bV8<4BXWi**u3NGE_&r@+UBFLLyb-at{iGjqp+q}0 z4wPc-2R82uoH&SYs%|xos%VO$v_`YI(HIdnnwks3(V8^{HR||-DFwqugohcsYO0%> znj;0MrJ4%V*3!CKEm43ioCOm0S|gOW2}+8>109{Y+g-$Ryu<O(fp zl6wDt;?5I2CXc^4cRLMkmP~$W z^WWoJ3p%=@ug8^j)N?odspWOip0=bqdc)L-GCWNTtx=vEPw$P zkGqT4n&pX^ps!+PSw(qb97&bIS_C?`V*-K~-${N6tu@!$ixWX@?b2Xed8K@<6-sn{ zrULaOgpKlw5bJ~z2}S!6qa_>@p|#G^#4BJC6>wnNrol#T$D@b5|R*$rL1hDux(Rst-WIQFTEn&M6baevwSNViv*i5-eZ-SW`V zs>BN*5FuAxv$Q<%II#ZY)fc{#zKahtV+oZ`0Yaf;hDpCBwD71%@} zEQ@{8zOSGj!8(2^L{xsJu)u8B`F>x0N_X zHarqnK>6@l`^PFNeu zA08_^ow$WuC_5cr{@KC3Y4YtS-S|Q{=*BDkF_bS00|&}fHGc5;l`ymOvGd8|r2YR! ze(>4kVe@j7vwKy3SOu$A;71P7uwFHO=b9!iw(m*PP-Z1^-4Jji@Y{vQ>|>5_`{mf~ zd2S!GuNgqKZw)tcaxMdf$)5p+?M}&=nlrB-PH^dG+HQ^yN}ma(uNUk2=JlI|sgo=y zdy^h3vvXkyyg)B9+ygdgZA{w2rrtR@o=rK*Vp00fH^@Y<{^kY#dHu+#-af_TQbYy% z!6G`)qz~znZeQ(5xQyd1#I79D3u;fo59G=I+LKy2K>VSE&(VHV9?nY!FDIv0jz5RY zp9{xba(tj^ve(WV3a^buNb}DzRfv>LgObkTM%bjIhW282QfLkzjp|(^j zFVeP<5>8&6qJ;3Mp6o_WALOh{a?DEQ>mmZG6|GWT8y%D49~dnb|8xuU*t2OM?PsEK zO?4ZcCWONp3QF~94QA2kaBIzI>3h@|byG&KzoDhId3AU+k7Zpl4(B>>Q+Sjf#<$F@ z8gwxYTaR`b_Cs}KwWnNQT8GUX%!VtUqghu&)WL2WG&Y4b?S< zbV+ECU$kQdzLr__jWpEPXjt!=MM`XV78Uc>`{rWh^hh6uO`2P; ztlP*(eOL*tF$S)$Zh-yAwQZBKhEXJZpq10$Tyvzlkvq$VbwcwcK0X=6I%)n~McynQ zoz!7ie=|oZ^;}<5SzDy8Nu7#f{aqVd;;T+!KQbRctJ^AEhGatL)38pPk1NC1`Y?Jx z1Lt5%G1qSWLz`deYr{xX4MfkFzfq#Kz81yIXkBesADcI-gk9rn!_bjhF=BmUCX`^K zuSIi8^q*R^#fMW$XbeWN|I%#4*T!rqdh0ZrV_2V>UnqOpd@VAXLvDVijcoR{d3@5) z=O$f0X%}uYeJzzOG>@R1`9hho3%8rTHl~wCy3FCD$;j={qcpv;uCA8yg<+K`{wrxb z4%)L!t6u5sf+I;2$|1|52(b(Agce3749m7oVj|owyxYwB8)Xp3qRCdf@E+5r4}>8b zeVV=B^hJvetB2KwpxcEHz-eU2HHMXA-KCs-81@pQ9P6bWdjw*L>eZM_!M7K%DBkSC z#~|vlO1zI2f70|dc^ZpaV4|-@pQl~;tm&)P2lH6{Ewe9iov@_}AAn&Eu+CTZz6Pl( z9-g$$v8Jie9fFk}m#1xe3v%jwAZwtu>nIqCFFJ0}I!}|QP2Z}N;|i^O>v4QRNDfQ! zOB&YKHDkEg8lPvg2t

0+e$ii<8rCPq{KV=fYCnpJ9(gD3cP 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 /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +/* +** Add the ability to override 'extern' +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif + +/* +** Make sure these symbols where not defined by some previous header +** file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers {F10010} +** +** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in +** the sqlite3.h file specify the version of SQLite with which +** that header file is associated. +** +** The "version" of SQLite is a strong of the form "X.Y.Z". +** The phrase "alpha" or "beta" might be appended after the Z. +** The X value is major version number always 3 in SQLite3. +** The X value only changes when backwards compatibility is +** broken and we intend to never break +** backwards compatibility. The Y value is the minor version +** number and only changes when +** there are major feature enhancements that are forwards compatible +** but not backwards compatible. The Z value is release number +** and is incremented with +** each release but resets back to 0 when Y is incremented. +** +** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. +** +** INVARIANTS: +** +** {F10011} The SQLITE_VERSION #define in the sqlite3.h header file +** evaluates to a string literal that is the SQLite version +** with which the header file is associated. +** +** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and +** Z are the major version, minor version, and release number. +*/ +#define SQLITE_VERSION "3.5.6" +#define SQLITE_VERSION_NUMBER 3005006 + +/* +** CAPI3REF: Run-Time Library Version Numbers {F10020} +** KEYWORDS: sqlite3_version +** +** These features provide the same information as the [SQLITE_VERSION] +** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated +** with the library instead of the header file. Cautious programmers might +** include a check in their application to verify that +** sqlite3_libversion_number() always returns the value +** [SQLITE_VERSION_NUMBER]. +** +** The sqlite3_libversion() function returns the same information as is +** in the sqlite3_version[] string constant. The function is provided +** for use in DLLs since DLL users usually do not have direct access to string +** constants within the DLL. +** +** INVARIANTS: +** +** {F10021} The [sqlite3_libversion_number()] interface returns an integer +** equal to [SQLITE_VERSION_NUMBER]. +** +** {F10022} The [sqlite3_version] string constant contains the text of the +** [SQLITE_VERSION] string. +** +** {F10023} The [sqlite3_libversion()] function returns +** a pointer to the [sqlite3_version] string constant. +*/ +SQLITE_EXTERN const char sqlite3_version[]; +const char *sqlite3_libversion(void); +int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} +** +** SQLite can be compiled with or without mutexes. When +** the SQLITE_THREADSAFE C preprocessor macro is true, mutexes +** are enabled and SQLite is threadsafe. When that macro os false, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite from more than one thread. +** +** There is a measurable performance penalty for enabling mutexes. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** The default behavior is for mutexes to be enabled. +** +** This interface can be used by a program to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the SQLITE_THREADSAFE macro. +** +** INVARIANTS: +** +** {F10101} The [sqlite3_threadsafe()] function returns nonzero if +** SQLite was compiled with its mutexes enabled or zero +** if SQLite was compiled with mutexes disabled. +*/ +int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle {F12000} +** KEYWORDS: {database connection} +** +** Each open SQLite database is represented by pointer to an instance of the +** opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors +** and [sqlite3_close()] is its destructor. There are many other interfaces +** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on this +** object. +*/ +typedef struct sqlite3 sqlite3; + + +/* +** CAPI3REF: 64-Bit Integer Types {F10200} +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type +** definitions. The sqlite_int64 and sqlite_uint64 types are +** supported for backwards compatibility only. +** +** INVARIANTS: +** +** {F10201} The [sqlite_int64] and [sqlite3_int64] types specify a +** 64-bit signed integer. +** +** {F10202} The [sqlite_uint64] and [sqlite3_uint64] types specify +** a 64-bit unsigned integer. +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection {F12010} +** +** This routine is the destructor for the [sqlite3] object. +** +** Applications should [sqlite3_finalize | finalize] all +** [prepared statements] and +** [sqlite3_blob_close | close] all [sqlite3_blob | BLOBs] +** associated with the [sqlite3] object prior +** to attempting to close the [sqlite3] object. +** +** What happens to pending transactions? Are they +** rolled back, or abandoned? +** +** INVARIANTS: +** +** {F12011} The [sqlite3_close()] interface destroys an [sqlite3] object +** allocated by a prior call to [sqlite3_open()], +** [sqlite3_open16()], or [sqlite3_open_v2()]. +** +** {F12012} The [sqlite3_close()] function releases all memory used by the +** connection and closes all open files. +** +** {F12013} If the database connection contains +** [prepared statements] that have not been +** finalized by [sqlite3_finalize()], then [sqlite3_close()] +** returns [SQLITE_BUSY] and leaves the connection open. +** +** {F12014} Giving sqlite3_close() a NULL pointer is a harmless no-op. +** +** LIMITATIONS: +** +** {U12015} The parameter to [sqlite3_close()] must be an [sqlite3] object +** pointer previously obtained from [sqlite3_open()] or the +** equivalent, or NULL. +** +** {U12016} The parameter to [sqlite3_close()] must not have been previously +** closed. +*/ +int sqlite3_close(sqlite3 *); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface {F12100} +** +** The sqlite3_exec() interface is a convenient way of running +** one or more SQL statements without a lot of C code. The +** SQL statements are passed in as the second parameter to +** sqlite3_exec(). The statements are evaluated one by one +** until either an error or an interrupt is encountered or +** until they are all done. The 3rd parameter is an optional +** callback that is invoked once for each row of any query results +** produced by the SQL statements. The 5th parameter tells where +** to write any error messages. +** +** The sqlite3_exec() interface is implemented in terms of +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()]. +** The sqlite3_exec() routine does nothing that cannot be done +** by [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()]. +** The sqlite3_exec() is just a convenient wrapper. +** +** INVARIANTS: +** +** {F12101} The [sqlite3_exec()] interface evaluates zero or more UTF-8 +** encoded, semicolon-separated, SQL statements in the +** zero-terminated string of its 2nd parameter within the +** context of the [sqlite3] object given in the 1st parameter. +** +** {F12104} The return value of [sqlite3_exec()] is SQLITE_OK if all +** SQL statements run successfully. +** +** {F12105} The return value of [sqlite3_exec()] is an appropriate +** non-zero error code if any SQL statement fails. +** +** {F12107} If one or more of the SQL statements handed to [sqlite3_exec()] +** return results and the 3rd parameter is not NULL, then +** the callback function specified by the 3rd parameter is +** invoked once for each row of result. +** +** {F12110} If the callback returns a non-zero value then [sqlite3_exec()] +** will aborted the SQL statement it is currently evaluating, +** skip all subsequent SQL statements, and return [SQLITE_ABORT]. +** What happens to *errmsg here? Does the result code for +** sqlite3_errcode() get set? +** +** {F12113} The [sqlite3_exec()] routine will pass its 4th parameter through +** as the 1st parameter of the callback. +** +** {F12116} The [sqlite3_exec()] routine sets the 2nd parameter of its +** callback to be the number of columns in the current row of +** result. +** +** {F12119} The [sqlite3_exec()] routine sets the 3rd parameter of its +** callback to be an array of pointers to strings holding the +** values for each column in the current result set row as +** obtained from [sqlite3_column_text()]. +** +** {F12122} The [sqlite3_exec()] routine sets the 4th parameter of its +** callback to be an array of pointers to strings holding the +** names of result columns as obtained from [sqlite3_column_name()]. +** +** {F12125} If the 3rd parameter to [sqlite3_exec()] is NULL then +** [sqlite3_exec()] never invokes a callback. All query +** results are silently discarded. +** +** {F12128} If an error occurs while parsing or evaluating any of the SQL +** statements handed to [sqlite3_exec()] then [sqlite3_exec()] will +** return an [error code] other than [SQLITE_OK]. +** +** {F12131} If an error occurs while parsing or evaluating any of the SQL +** handed to [sqlite3_exec()] and if the 5th parameter (errmsg) +** to [sqlite3_exec()] is not NULL, then an error message is +** allocated using the equivalent of [sqlite3_mprintf()] and +** *errmsg is made to point to that message. +** +** {F12134} The [sqlite3_exec()] routine does not change the value of +** *errmsg if errmsg is NULL or if there are no errors. +** +** {F12137} The [sqlite3_exec()] function sets the error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** +** LIMITATIONS: +** +** {U12141} The first parameter to [sqlite3_exec()] must be an valid and open +** [database connection]. +** +** {U12142} The database connection must not be closed while +** [sqlite3_exec()] is running. +** +** {U12143} The calling function is should use [sqlite3_free()] to free +** the memory that *errmsg is left pointing at once the error +** message is no longer needed. +** +** {U12145} The SQL statement text in the 2nd parameter to [sqlite3_exec()] +** must remain unchanged while [sqlite3_exec()] is running. +*/ +int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluted */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes {F10210} +** KEYWORDS: SQLITE_OK {error code} {error codes} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicates success or failure. +** +** See also: [SQLITE_IOERR_READ | extended result codes] +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes {F10220} +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result codes} +** +** In its default configuration, SQLite API routines return one of 26 integer +** [SQLITE_OK | result codes]. However, experience has shown that +** many of these result codes are too course-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. The extended result codes are enabled or disabled +** for each database connection using the [sqlite3_extended_result_codes()] +** API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +** +** INVARIANTS: +** +** {F10223} The symbolic name for an extended result code always contains +** a related primary result code as a prefix. +** +** {F10224} Primary result code names contain a single "_" character. +** +** {F10225} Extended result code names contain two or more "_" characters. +** +** {F10226} The numeric value of an extended result code contains the +** numeric value of its corresponding primary result code it +** its least significant 8 bits. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) + +/* +** CAPI3REF: Flags For File Open Operations {F10230} +** +** These bit values are intended for use in then +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the xOpen method of the +** [sqlite3_vfs] object. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 +#define SQLITE_OPEN_READWRITE 0x00000002 +#define SQLITE_OPEN_CREATE 0x00000004 +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 +#define SQLITE_OPEN_MAIN_DB 0x00000100 +#define SQLITE_OPEN_TEMP_DB 0x00000200 +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 + +/* +** CAPI3REF: Device Characteristics {F10240} +** +** The xDeviceCapabilities method of the [sqlite3_io_methods] +** object returns an integer which is a vector of the these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 + +/* +** CAPI3REF: File Locking Levels {F10250} +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags {F10260} +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of the +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. The SQLITE_SYNC_NORMAL means +** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means +** to use Mac OS-X style fullsync instead of fsync(). +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + + +/* +** CAPI3REF: OS Interface Open File Handle {F11110} +** +** An [sqlite3_file] object represents an open file in the OS +** interface layer. Individual OS interface implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file { + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object {F11120} +** +** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to +** an instance of the this object. This object defines the +** methods used to perform various operations against the open file. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +* The second choice is an +** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to +** indicate that only the data of the file and not its inode needs to be +** synced. +** +** The integer values to xLock() and xUnlock() are one of +**

+** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method looks +** to see if any database connection, either in this +** process or in some other process, is holding an RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false if not. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument +** is an integer opcode. The third +** argument is a generic pointer which is intended to be a pointer +** to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves opcodes less than 100 for its own use. +** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
+** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods { + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes {F11310} +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] +** interface. +** +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode cases 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. +*/ +#define SQLITE_FCNTL_LOCKSTATE 1 + +/* +** CAPI3REF: Mutex Handle {F17110} +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: OS Interface Object {F11140} +** +** An instance of this object defines the interface between the +** SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". +** +** The iVersion field is initially 1 but may be larger for future +** versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered vfs modules are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. +** +** The pNext field is the only fields in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** {F11141} SQLite will guarantee that the zFilename string passed to +** xOpen() is a full pathname as generated by xFullPathname() and +** that the string will be valid and unchanged until xClose() is +** called. {END} So the [sqlite3_file] can store a pointer to the +** filename if it needs to remember the filename for some reason. +** +** {F11142} The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be +** set. +** +** {F11143} SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
    +**
  • [SQLITE_OPEN_MAIN_DB] +**
  • [SQLITE_OPEN_MAIN_JOURNAL] +**
  • [SQLITE_OPEN_TEMP_DB] +**
  • [SQLITE_OPEN_TEMP_JOURNAL] +**
  • [SQLITE_OPEN_TRANSIENT_DB] +**
  • [SQLITE_OPEN_SUBJOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] +**
{END} +** +** The file I/O implementation can use the object type flags to +** changes the way it deals with files. For example, an application +** that does not care about crash recovery or rollback, might make +** the open of a journal file a no-op. Writes to this journal are +** also a no-op. Any attempt to read the journal return SQLITE_IOERR. +** Or the implementation might recognize the a database file will +** be doing page-aligned sector reads and writes in a random order +** and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen +** method: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases, journals and for subjournals. +** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened +** for exclusive access. This flag is set for all files except +** for the main database file. {END} +** +** {F11148} At least szOsFile bytes of memory is allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. {END} The xOpen method does not have to +** allocate the structure; it should just fill it in. +** +** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existance of a file, +** or [SQLITE_ACCESS_READWRITE] to test to see +** if a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test to see if a file is at least readable. {END} The file can be a +** directory. +** +** {F11150} SQLite will always allocate at least mxPathname+1 byte for +** the output buffers for xGetTempname and xFullPathname. {F11151} The exact +** size of the output buffer is also passed as a parameter to both +** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN +** should be returned. As this is handled as a fatal error by SQLite, +** vfs implementations should endeavor to prevent this by setting +** mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), and xCurrentTime() interfaces +** are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. The +** xSleep() method cause the calling thread to sleep for at +** least the number of microseconds given. The xCurrentTime() +** method returns a Julian Day Number for the current date and +** time. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +struct sqlite3_vfs { + int iVersion; /* Structure version number */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); + int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + /* New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method {F11190} +** +** {F11191} These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. {END} They determine +** the kind of what kind of permissions the xAccess method is +** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks to see if the file exists. {F11193} With +** SQLITE_ACCESS_READWRITE, the xAccess method checks to see +** if the file is both readable and writable. {F11194} With +** SQLITE_ACCESS_READ the xAccess method +** checks to see if the file is readable. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 +#define SQLITE_ACCESS_READ 2 + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} +** +** The sqlite3_extended_result_codes() routine enables or disables the +** [SQLITE_IOERR_READ | extended result codes] feature of SQLite. +** The extended result codes are disabled by default for historical +** compatibility. +** +** INVARIANTS: +** +** {F12201} Each new [database connection] has the +** [extended result codes] feature +** disabled by default. +** +** {F12202} The [sqlite3_extended_result_codes(D,F)] interface will enable +** [extended result codes] for the +** [database connection] D if the F parameter +** is true, or disable them if F is false. +*/ +int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid {F12220} +** +** Each entry in an SQLite table has a unique 64-bit signed +** integer key called the "rowid". The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. If +** the table has a column of type INTEGER PRIMARY KEY then that column +** is another an alias for the rowid. +** +** This routine returns the rowid of the most recent +** successful INSERT into the database from the database connection +** shown in the first argument. If no successful inserts +** have ever occurred on this database connection, zero is returned. +** +** If an INSERT occurs within a trigger, then the rowid of the +** inserted row is returned by this routine as long as the trigger +** is running. But once the trigger terminates, the value returned +** by this routine reverts to the last value inserted before the +** trigger fired. +** +** An INSERT that fails due to a constraint violation is not a +** successful insert and does not change the value returned by this +** routine. Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface. +** +** For the purposes of this routine, an insert is considered to +** be successful even if it is subsequently rolled back. +** +** INVARIANTS: +** +** {F12221} The [sqlite3_last_insert_rowid()] function returns the +** rowid of the most recent successful insert done +** on the same database connection and within the same +** trigger context, or zero if there have +** been no qualifying inserts on that connection. +** +** {F12223} The [sqlite3_last_insert_rowid()] function returns +** same value when called from the same trigger context +** immediately before and after a ROLLBACK. +** +** LIMITATIONS: +** +** {U12232} If separate thread does a new insert on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert rowid, +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert rowid. +*/ +sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified {F12240} +** +** This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the connection specified by the first parameter. Only +** changes that are directly specified by the INSERT, UPDATE, or +** DELETE statement are counted. Auxiliary changes caused by +** triggers are not counted. Use the [sqlite3_total_changes()] function +** to find the total number of changes including changes caused by triggers. +** +** A "row changes" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of REPLACE constraint resolution, +** rollback, ABORT processing, DROP TABLE, or by any other +** mechanisms do not count as direct row changes. +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a trigger. Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** So when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. +** Within the body of a trigger, the sqlite3_changes() interface +** can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the same trigger. +** However, the number returned does not include in changes +** caused by subtriggers since they have their own context. +** +** SQLite implements the command "DELETE FROM table" without +** a WHERE clause by dropping and recreating the table. (This is much +** faster than going through and deleting individual elements from the +** table.) Because of this optimization, the deletions in +** "DELETE FROM table" are not row changes and will not be counted +** by the sqlite3_changes() or [sqlite3_total_changes()] functions. +** To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +** +** INVARIANTS: +** +** {F12241} The [sqlite3_changes()] function returns the number of +** row changes caused by the most recent INSERT, UPDATE, +** or DELETE statement on the same database connection and +** within the same trigger context, or zero if there have +** not been any qualifying row changes. +** +** LIMITATIONS: +** +** {U12252} If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and unmeaningful. +*/ +int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified {F12260} +*** +** This function returns the number of row changes caused +** by INSERT, UPDATE or DELETE statements since the database handle +** was opened. The count includes all changes from all trigger +** contexts. But the count does not include changes used to +** implement REPLACE constraints, do rollbacks or ABORT processing, +** or DROP table processing. +** The changes +** are counted as soon as the statement that makes them is completed +** (when the statement handle is passed to [sqlite3_reset()] or +** [sqlite3_finalize()]). +** +** SQLite implements the command "DELETE FROM table" without +** a WHERE clause by dropping and recreating the table. (This is much +** faster than going +** through and deleting individual elements form the table.) Because of +** this optimization, the change count for "DELETE FROM table" will be +** zero regardless of the number of elements that were originally in the +** table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +** +** See also the [sqlite3_changes()] interface. +** +** INVARIANTS: +** +** {F12261} The [sqlite3_total_changes()] returns the total number +** of row changes caused by INSERT, UPDATE, and/or DELETE +** statements on the same [database connection], in any +** trigger context, since the database connection was +** created. +** +** LIMITATIONS: +** +** {U12264} If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and unmeaningful. +*/ +int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query {F12270} +** +** This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a database connection that +** is closed or might close before sqlite3_interrupt() returns. +** +** If an SQL is very nearly finished at the time when sqlite3_interrupt() +** is called, then it might not have an opportunity to be interrupted. +** It might continue to completion. +** An SQL operation that is interrupted will return +** [SQLITE_INTERRUPT]. If the interrupted SQL operation is an +** INSERT, UPDATE, or DELETE that is inside an explicit transaction, +** then the entire transaction will be rolled back automatically. +** A call to sqlite3_interrupt() has no effect on SQL statements +** that are started after sqlite3_interrupt() returns. +** +** INVARIANTS: +** +** {F12271} The [sqlite3_interrupt()] interface will force all running +** SQL statements associated with the same database connection +** to halt after processing at most one additional row of +** data. +** +** {F12272} Any SQL statement that is interrupted by [sqlite3_interrupt()] +** will return [SQLITE_INTERRUPT]. +** +** LIMITATIONS: +** +** {U12279} If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} +** +** These routines are useful for command-line input to determine if the +** currently entered text seems to form complete a SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. These routines return true if the input string +** appears to be a complete SQL statement. A statement is judged to be +** complete if it ends with a semicolon token and is not a fragment of a +** CREATE TRIGGER statement. Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. +** +** These routines do not parse the SQL and +** so will not detect syntactically incorrect SQL. +** +** INVARIANTS: +** +** {F10511} The sqlite3_complete() and sqlite3_complete16() functions +** return true (non-zero) if and only if the last +** non-whitespace token in their input is a semicolon that +** is not in between the BEGIN and END of a CREATE TRIGGER +** statement. +** +** LIMITATIONS: +** +** {U10512} The input to sqlite3_complete() must be a zero-terminated +** UTF-8 string. +** +** {U10513} The input to sqlite3_complete16() must be a zero-terminated +** UTF-16 string in native byte order. +*/ +int sqlite3_complete(const char *sql); +int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} +** +** This routine identifies a callback function that might be +** invoked whenever an attempt is made to open a database table +** that another thread or process has locked. +** If the busy callback is NULL, then [SQLITE_BUSY] +** or [SQLITE_IOERR_BLOCKED] +** is returned immediately upon encountering the lock. +** If the busy callback is not NULL, then the +** callback will be invoked with two arguments. The +** first argument to the handler is a copy of the void* pointer which +** is the third argument to this routine. The second argument to +** the handler is the number of times that the busy handler has +** been invoked for this locking event. If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. +** If the callback returns non-zero, then another attempt +** is made to open the database for reading and the cycle repeats. +** +** The presence of a busy handler does not guarantee that +** it will be invoked when there is lock contention. +** If SQLite determines that invoking the busy handler could result in +** a deadlock, it will go ahead and return [SQLITE_BUSY] or +** [SQLITE_IOERR_BLOCKED] instead of invoking the +** busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** The default busy callback is NULL. +** +** The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] +** when SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. This error code promotion +** forces an automatic rollback of the changes. See the +**
+** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** There can only be a single busy handler defined for each database +** connection. Setting a new busy handler clears any previous one. +** Note that calling [sqlite3_busy_timeout()] will also set or clear +** the busy handler. +** +** INVARIANTS: +** +** {F12311} The [sqlite3_busy_handler()] function replaces the busy handler +** callback in the database connection identified by the 1st +** parameter with a new busy handler identified by the 2nd and 3rd +** parameters. +** +** {F12312} The default busy handler for new database connections is NULL. +** +** {F12314} When two or more database connection share a common cache, +** the busy handler for the database connection currently using +** the cache is invoked when the cache encounters a lock. +** +** {F12316} If a busy handler callback returns zero, then the SQLite +** interface that provoked the locking event will return +** [SQLITE_BUSY]. +** +** {F12318} SQLite will invokes the busy handler with two argument which +** are a copy of the pointer supplied by the 3rd parameter to +** [sqlite3_busy_handler()] and a count of the number of prior +** invocations of the busy handler for the same locking event. +** +** LIMITATIONS: +** +** {U12319} A busy handler should not call close the database connection +** or prepared statement that invoked the busy handler. +*/ +int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout {F12340} +** +** This routine sets a [sqlite3_busy_handler | busy handler] +** that sleeps for a while when a +** table is locked. The handler will sleep multiple times until +** at least "ms" milliseconds of sleeping have been done. {F12343} After +** "ms" milliseconds of sleeping, the handler returns 0 which +** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** There can only be a single busy handler for a particular database +** connection. If another busy handler was defined +** (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared. +** +** INVARIANTS: +** +** {F12341} The [sqlite3_busy_timeout()] function overrides any prior +** [sqlite3_busy_timeout()] or [sqlite3_busy_handler()] setting +** on the same database connection. +** +** {F12343} If the 2nd parameter to [sqlite3_busy_timeout()] is less than +** or equal to zero, then the busy handler is cleared so that +** all subsequent locking events immediately return [SQLITE_BUSY]. +** +** {F12344} If the 2nd parameter to [sqlite3_busy_timeout()] is a positive +** number N, then a busy handler is set that repeatedly calls +** the xSleep() method in the VFS interface until either the +** lock clears or until the cumulative sleep time reported back +** by xSleep() exceeds N milliseconds. +*/ +int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries {F12370} +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated +** UTF-8 strings. There are (N+1)*M elements in the array. +** The first M pointers point to zero-terminated strings that +** contain the names of the columns. +** The remaining entries all point to query results. NULL +** values are give a NULL pointer. All other values are in +** their UTF-8 zero-terminated string representation as returned by +** [sqlite3_column_text()]. +** +** A result table might consists of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** As an example of the result table format, suppose a query result +** is as follows: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
+** +** The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter. It returns a result table to the +** pointer given in its 3rd parameter. +** +** After the calling function has finished using the result, it should +** pass the pointer to the result table to sqlite3_free_table() in order to +** release the memory that was malloc-ed. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +** +** INVARIANTS: +** +** {F12371} If a [sqlite3_get_table()] fails a memory allocation, then +** it frees the result table under construction, aborts the +** query in process, skips any subsequent queries, sets the +** *resultp output pointer to NULL and returns [SQLITE_NOMEM]. +** +** {F12373} If the ncolumn parameter to [sqlite3_get_table()] is not NULL +** then [sqlite3_get_table()] write the number of columns in the +** result set of the query into *ncolumn if the query is +** successful (if the function returns SQLITE_OK). +** +** {F12374} If the nrow parameter to [sqlite3_get_table()] is not NULL +** then [sqlite3_get_table()] write the number of rows in the +** result set of the query into *nrow if the query is +** successful (if the function returns SQLITE_OK). +** +** {F12376} The [sqlite3_get_table()] function sets its *ncolumn value +** to the number of columns in the result set of the query in the +** sql parameter, or to zero if the query in sql has an empty +** result set. +*/ +int sqlite3_get_table( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + char ***pResult, /* Results of the query */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg /* Error msg written here */ +); +void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions {F17400} +** +** These routines are workalikes of the "printf()" family of functions +** from the standard C library. +** +** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** In sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf(). This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer. We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** 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. +** +** The %q option works like %s in that it substitutes a null-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal. By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, so some string variable contains text as follows: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** This second example is an SQL syntax error. As a general rule you +** should always use %q instead of %s when inserting text into a string +** literal. +** +** The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Or if the parameter in the argument +** list is a NULL pointer, %Q substitutes the text "NULL" (without single +** quotes) in place of the %Q option. {END} So, for example, one could say: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** The "%z" formatting option works exactly like "%s" with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string. {END} +** +** INVARIANTS: +** +** {F17403} The [sqlite3_mprintf()] and [sqlite3_vmprintf()] interfaces +** return either pointers to zero-terminated UTF-8 strings held in +** memory obtained from [sqlite3_malloc()] or NULL pointers if +** a call to [sqlite3_malloc()] fails. +** +** {F17406} The [sqlite3_snprintf()] interface writes a zero-terminated +** UTF-8 string into the buffer pointed to by the second parameter +** provided that the first parameter is greater than zero. +** +** {F17407} The [sqlite3_snprintf()] interface does not writes slots of +** its output buffer (the second parameter) outside the range +** of 0 through N-1 (where N is the first parameter) +** regardless of the length of the string +** requested by the format specification. +** +*/ +char *sqlite3_mprintf(const char*,...); +char *sqlite3_vmprintf(const char*, va_list); +char *sqlite3_snprintf(int,char*,const char*, ...); + +/* +** CAPI3REF: Memory Allocation Subsystem {F17300} +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** windows VFS uses native malloc and free for some operations. +** +** The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_free(). +** +** The sqlite3_realloc() interface attempts to resize a +** prior memory allocation to be at least N bytes, where N is the +** second parameter. The memory allocation to be resized is the first +** parameter. If the first parameter to sqlite3_realloc() +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). +** If the second parameter to sqlite3_realloc() is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). +** Sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. +** If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc() and the prior allocation is freed. +** If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. +** +** The memory returned by sqlite3_malloc() and sqlite3_realloc() +** is always aligned to at least an 8 byte boundary. {END} +** +** The default implementation +** of the memory allocation subsystem uses the malloc(), realloc() +** and free() provided by the standard C library. {F17382} However, if +** SQLite is compiled with the following C preprocessor macro +** +**
SQLITE_MEMORY_SIZE=NNN
+** +** where NNN is an integer, then SQLite create a static +** array of at least NNN bytes in size and use that array +** for all of its dynamic memory allocation needs. {END} Additional +** memory allocator options may be added in future releases. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be +** used. +** +** The windows OS interface layer calls +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular windows +** installation. Memory allocation errors are detected, but +** they are reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** INVARIANTS: +** +** {F17303} The [sqlite3_malloc(N)] interface returns either a pointer to +** newly checked-out block of at least N bytes of memory +** that is 8-byte aligned, +** or it returns NULL if it is unable to fulfill the request. +** +** {F17304} The [sqlite3_malloc(N)] interface returns a NULL pointer if +** N is less than or equal to zero. +** +** {F17305} The [sqlite3_free(P)] interface releases memory previously +** returned from [sqlite3_malloc()] or [sqlite3_realloc()], +** making it available for reuse. +** +** {F17306} A call to [sqlite3_free(NULL)] is a harmless no-op. +** +** {F17310} A call to [sqlite3_realloc(0,N)] is equivalent to a call +** to [sqlite3_malloc(N)]. +** +** {F17312} A call to [sqlite3_realloc(P,0)] is equivalent to a call +** to [sqlite3_free(P)]. +** +** {F17315} The SQLite core uses [sqlite3_malloc()], [sqlite3_realloc()], +** and [sqlite3_free()] for all of its memory allocation and +** deallocation needs. +** +** {F17318} The [sqlite3_realloc(P,N)] interface returns either a pointer +** to a block of checked-out memory of at least N bytes in size +** that is 8-byte aligned, or a NULL pointer. +** +** {F17321} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first +** copies the first K bytes of content from P into the newly allocated +** where K is the lessor of N and the size of the buffer P. +** +** {F17322} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first +** releases the buffer P. +** +** {F17323} When [sqlite3_realloc(P,N)] returns NULL, the buffer P is +** not modified or released. +** +** LIMITATIONS: +** +** {U17350} The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else a pointer obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that has +** not been released. +** +** {U17351} The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +** +*/ +void *sqlite3_malloc(int); +void *sqlite3_realloc(void*, int); +void sqlite3_free(void*); + +/* +** CAPI3REF: Memory Allocator Statistics {F17370} +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** the memory allocation subsystem included within the SQLite. +** +** INVARIANTS: +** +** {F17371} The [sqlite3_memory_used()] routine returns the +** number of bytes of memory currently outstanding +** (malloced but not freed). +** +** {F17373} The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] +** since the highwater mark was last reset. +** +** {F17374} The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** {F17375} The memory highwater mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. The value returned +** by [sqlite3_memory_highwater(1)] is the highwater mark +** prior to the reset. +*/ +sqlite3_int64 sqlite3_memory_used(void); +sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks {F12500} +** +** This routine registers a authorizer callback with a particular +** database connection, supplied in the first argument. +** The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. The authorizer callback should +** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. If the authorizer code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the prepared +** statement is constructed to insert a NULL value in place of +** the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** +** The first parameter to the authorizer callback is a copy of +** the third parameter to the sqlite3_set_authorizer() interface. +** The second parameter to the callback is an integer +** [SQLITE_COPY | action code] that specifies the particular action +** to be authorized. The third through sixth +** parameters to the callback are zero-terminated strings that contain +** additional details about the action to be authorized. +** +** An authorizer is used when preparing SQL statements from an untrusted +** source, to ensure that the SQL statements do not try to access data +** that they are not allowed to see, or that they do not try to +** execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being prepared that disallows everything +** except SELECT statements. +** +** Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call. Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()]. +** +** INVARIANTS: +** +** {F12501} The [sqlite3_set_authorizer(D,...)] interface registers a +** authorizer callback with database connection D. +** +** {F12502} The authorizer callback is invoked as SQL statements are +** being compiled +** +** {F12503} If the authorizer callback returns any value other than +** [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] then +** the [sqlite3_prepare_v2()] or equivalent call that caused +** the authorizer callback to run shall fail with an +** [SQLITE_ERROR] error code and an appropriate error message. +** +** {F12504} When the authorizer callback returns [SQLITE_OK], the operation +** described is coded normally. +** +** {F12505} When the authorizer callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that caused the +** authorizer callback to run shall fail +** with an [SQLITE_ERROR] error code and an error message +** explaining that access is denied. +** +** {F12506} If the authorizer code (the 2nd parameter to the authorizer +** callback) is [SQLITE_READ] and the authorizer callback returns +** [SQLITE_IGNORE] then the prepared statement is constructed to +** insert a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. +** +** {F12507} If the authorizer code (the 2nd parameter to the authorizer +** callback) is anything other than [SQLITE_READ], then +** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. +** +** {F12510} The first parameter to the authorizer callback is a copy of +** the third parameter to the [sqlite3_set_authorizer()] interface. +** +** {F12511} The second parameter to the callback is an integer +** [SQLITE_COPY | action code] that specifies the particular action +** to be authorized. +** +** {F12512} The third through sixth parameters to the callback are +** zero-terminated strings that contain +** additional details about the action to be authorized. +** +** {F12520} Each call to [sqlite3_set_authorizer()] overrides the +** any previously installed authorizer. +** +** {F12521} A NULL authorizer means that no authorization +** callback is invoked. +** +** {F12522} The default authorizer is NULL. +*/ +int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes {F12590} +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes {F12550} +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorizer certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable. The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +** +** INVARIANTS: +** +** {F12551} The second parameter to an +** [sqlite3_set_authorizer | authorizer callback is always an integer +** [SQLITE_COPY | authorizer code] that specifies what action +** is being authorized. +** +** {F12552} The 3rd and 4th parameters to the +** [sqlite3_set_authorizer | authorization callback function] +** will be parameters or NULL depending on which +** [SQLITE_COPY | authorizer code] is used as the second parameter. +** +** {F12553} The 5th parameter to the +** [sqlite3_set_authorizer | authorizer callback] is the name +** of the database (example: "main", "temp", etc.) if applicable. +** +** {F12554} The 6th parameter to the +** [sqlite3_set_authorizer | authorizer callback] is the name +** of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* NULL NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* Function Name NULL */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions {F12280} +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** The callback returns a UTF-8 rendering of the SQL statement text +** as the statement first begins executing. Additional callbacks occur +** as each triggersubprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger. +** +** The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. +** +** The sqlite3_profile() API is currently considered experimental and +** is subject to change or removal in a future release. +** +** The trigger reporting feature of the trace callback is considered +** experimental and is subject to change or removal in future releases. +** Future versions of SQLite might also add new trace callback +** invocations. +** +** INVARIANTS: +** +** {F12281} The callback function registered by [sqlite3_trace()] is +** whenever an SQL statement first begins to execute and +** whenever a trigger subprogram first begins to run. +** +** {F12282} Each call to [sqlite3_trace()] overrides the previously +** registered trace callback. +** +** {F12283} A NULL trace callback disables tracing. +** +** {F12284} The first argument to the trace callback is a copy of +** the pointer which was the 3rd argument to [sqlite3_trace()]. +** +** {F12285} The second argument to the trace callback is a +** zero-terminated UTF8 string containing the original text +** of the SQL statement as it was passed into [sqlite3_prepare_v2()] +** or the equivalent, or an SQL comment indicating the beginning +** of a trigger subprogram. +** +** {F12287} The callback function registered by [sqlite3_profile()] is invoked +** as each SQL statement finishes. +** +** {F12288} The first parameter to the profile callback is a copy of +** the 3rd parameter to [sqlite3_profile()]. +** +** {F12289} The second parameter to the profile callback is a +** zero-terminated UTF-8 string that contains the complete text of +** the SQL statement as it was processed by [sqlite3_prepare_v2()] +** or the equivalent. +** +** {F12290} The third parameter to the profile callback is an estimate +** of the number of nanoseconds of wall-clock time required to +** run the SQL statement from start to finish. +*/ +void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks {F12910} +** +** This routine configures a callback function - the +** progress callback - that is invoked periodically during long +** running calls to [sqlite3_exec()], [sqlite3_step()] and +** [sqlite3_get_table()]. An example use for this +** interface is to keep a GUI updated during a large query. +** +** If the progress callback returns non-zero, the opertion is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI dialog box. +** +** INVARIANTS: +** +** {F12911} The callback function registered by [sqlite3_progress_handler()] +** is invoked periodically during long running calls to +** [sqlite3_step()]. +** +** {F12912} The progress callback is invoked once for every N virtual +** machine opcodes, where N is the second argument to +** the [sqlite3_progress_handler()] call that registered +** the callback. What if N is less than 1? +** +** {F12913} The progress callback itself is identified by the third +** argument to [sqlite3_progress_handler()]. +** +** {F12914} The fourth argument [sqlite3_progress_handler()] is a +*** void pointer passed to the progress callback +** function each time it is invoked. +** +** {F12915} If a call to [sqlite3_step()] results in fewer than +** N opcodes being executed, +** then the progress callback is never invoked. {END} +** +** {F12916} Every call to [sqlite3_progress_handler()] +** overwrites any previously registere progress handler. +** +** {F12917} If the progress handler callback is NULL then no progress +** handler is invoked. +** +** {F12918} If the progress callback returns a result other than 0, then +** the behavior is a if [sqlite3_interrupt()] had been called. +*/ +void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection {F12700} +** +** These routines open an SQLite database file whose name +** is given by the filename argument. +** The filename argument is interpreted as UTF-8 +** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 +** in the native byte order for [sqlite3_open16()]. +** An [sqlite3*] handle is usually returned in *ppDb, even +** if an error occurs. The only exception is if SQLite is unable +** to allocate memory to hold the [sqlite3] object, a NULL will +** be written into *ppDb instead of a pointer to the [sqlite3] object. +** If the database is opened (and/or created) +** successfully, then [SQLITE_OK] is returned. Otherwise an +** error code is returned. The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error. +** +** The default encoding for the database will be UTF-8 if +** [sqlite3_open()] or [sqlite3_open_v2()] is called and +** UTF-16 in the native byte order if [sqlite3_open16()] is used. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [sqlite3*] handle should be released by passing it +** to [sqlite3_close()] when it is no longer required. +** +** The [sqlite3_open_v2()] interface works like [sqlite3_open()] +** except that it acccepts two additional parameters for additional control +** over the new database connection. The flags parameter can be +** one of: +** +**
    +**
  1. [SQLITE_OPEN_READONLY] +**
  2. [SQLITE_OPEN_READWRITE] +**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] +**
+** +** The first value opens the database read-only. +** If the database does not previously exist, an error is returned. +** The second option opens +** the database for reading and writing if possible, or reading only if +** if the file is write protected. In either case the database +** must already exist or an error is returned. The third option +** opens the database for reading and writing and creates it if it does +** not already exist. +** The third options is behavior that is always used for [sqlite3_open()] +** and [sqlite3_open16()]. +** +** If the filename is ":memory:", then an private +** in-memory database is created for the connection. This in-memory +** database will vanish when the database connection is closed. Future +** version of SQLite might make use of additional special filenames +** that begin with the ":" character. It is recommended that +** when a database filename really does begin with +** ":" that you prefix the filename with a pathname like "./" to +** avoid ambiguity. +** +** If the filename is an empty string, then a private temporary +** on-disk database will be created. This private database will be +** automatically deleted as soon as the database connection is closed. +** +** The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system +** interface that the new database connection should use. If the +** fourth parameter is a NULL pointer then the default [sqlite3_vfs] +** object is used. +** +** Note to windows users: The encoding used for the filename argument +** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** [sqlite3_open()] or [sqlite3_open_v2()]. +** +** INVARIANTS: +** +** {F12701} The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces create a new +** [database connection] associated with +** the database file given in their first parameter. +** +** {F12702} The filename argument is interpreted as UTF-8 +** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 +** in the native byte order for [sqlite3_open16()]. +** +** {F12703} A successful invocation of [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] writes a pointer to a new +** [database connection] into *ppDb. +** +** {F12704} The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces return [SQLITE_OK] upon success, +** or an appropriate [error code] on failure. +** +** {F12706} The default text encoding for a new database created using +** [sqlite3_open()] or [sqlite3_open_v2()] will be UTF-8. +** +** {F12707} The default text encoding for a new database created using +** [sqlite3_open16()] will be UTF-16. +** +** {F12709} The [sqlite3_open(F,D)] interface is equivalent to +** [sqlite3_open_v2(F,D,G,0)] where the G parameter is +** [SQLITE_OPEN_READWRITE]|[SQLITE_OPEN_CREATE]. +** +** {F12711} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the +** bit value [SQLITE_OPEN_READONLY] then the database is opened +** for reading only. +** +** {F12712} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the +** bit value [SQLITE_OPEN_READWRITE] then the database is opened +** reading and writing if possible, or for reading only if the +** file is write protected by the operating system. +** +** {F12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the +** bit value [SQLITE_OPEN_CREATE] and the database does not +** previously exist, an error is returned. +** +** {F12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the +** bit value [SQLITE_OPEN_CREATE] and the database does not +** previously exist, then an attempt is made to create and +** initialize the database. +** +** {F12717} If the filename argument to [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] is ":memory:", then an private, +** ephemeral, in-memory database is created for the connection. +** Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required +** in sqlite3_open_v2()? +** +** {F12719} If the filename is an empty string, then a private, ephermeral +** on-disk database will be created. +** Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required +** in sqlite3_open_v2()? +** +** {F12721} The [database connection] created by +** [sqlite3_open_v2(F,D,G,V)] will use the +** [sqlite3_vfs] object identified by the V parameter, or +** the default [sqlite3_vfs] object is V is a NULL pointer. +*/ +int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Error Codes And Messages {F12800} +** +** The sqlite3_errcode() interface returns the numeric +** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] +** for the most recent failed sqlite3_* API call associated +** with [sqlite3] handle 'db'. If a prior API call failed but the +** most recent API call succeeded, the return value from sqlite3_errcode() +** is undefined. +** +** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF8 or UTF16 respectively. +** Memory to hold the error message string is managed internally. +** The application does not need to worry with freeing the result. +** However, the error string might be overwritten or deallocated b +** subsequent calls to other SQLite interface functions. +** +** INVARIANTS: +** +** {F12801} The [sqlite3_errcode(D)] interface returns the numeric +** [SQLITE_OK | result code] or +** [SQLITE_IOERR_READ | extended result code] +** for the most recent failed interface call associated +** with [sqlite3] handle D. +** +** {U12802} If a prior API call failed but the most recent API call +** succeeded, the return value from [sqlite3_errcode()], +** [sqlite3_errmsg()], and [sqlite3_errmsg16()] are undefined. +** +** {F12803} The [sqlite3_errmsg(D)] and [sqlite3_errmsg16(D)] +** interfaces return English-language text that describes +** the error in the mostly recently failed interface call, +** encoded as either UTF8 or UTF16 respectively. +** +** {U12804} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()] +** are only valid until the next SQLite interface call. +** +** {F12807} Calls to [sqlite3_errcode()], [sqlite3_errmsg()], and +** [sqlite3_errmsg16()] themselves do not affect the +** results of future invocations of these routines. +** +** {F12808} Calls to API routines that do not return an error code +** (example: [sqlite3_data_count()]) do not +** change the error code or message returned by +** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()]. +** +** {F12809} Interfaces that are not associated with a specific +** [database connection] (examples: +** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] +** do not change the values returned by +** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()]. +*/ +int sqlite3_errcode(sqlite3 *db); +const char *sqlite3_errmsg(sqlite3*); +const void *sqlite3_errmsg16(sqlite3*); + +/* +** CAPI3REF: SQL Statement Object {F13000} +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represent single SQL statements. This +** object is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". +** +** The life of a statement object goes something like this: +** +**
    +**
  1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
  2. Bind values to host parameters using +** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+** +** Refer to documentation on individual methods above for additional +** information. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Compiling An SQL Statement {F13010} +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument "db" is an [database connection] +** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] +** or [sqlite3_open16()]. +** The second argument "zSql" is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. {END} +** +** 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 +** until the nByte-th byte, whichever comes first. {END} +** +** *pzTail is made to point to the first byte past the end of the +** first SQL statement in zSql. These routines only compiles the first +** statement in zSql, so *pzTail is left pointing to what remains +** uncompiled. +** +** *ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be +** set to NULL. If the input text contains no SQL (if the input +** is and empty string or a comment) then *ppStmt is set to NULL. +** {U13018} The calling procedure is responsible for deleting the +** compiled SQL statement +** using [sqlite3_finalize()] after it has finished with it. +** +** On success, [SQLITE_OK] is returned. Otherwise an +** [error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. {END} This causes the [sqlite3_step()] interface to +** behave a differently in two ways: +** +**
    +**
  1. +** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. If the schema has changed in +** a way that makes the statement no longer valid, [sqlite3_step()] will still +** return [SQLITE_SCHEMA]. But unlike the legacy behavior, +** [SQLITE_SCHEMA] is now a fatal error. Calling +** [sqlite3_prepare_v2()] again will not make the +** error go away. Note: use [sqlite3_errmsg()] to find the text +** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} +**
  2. +** +**
  3. +** When an error occurs, +** [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. +** The legacy behavior was that [sqlite3_step()] would only return a generic +** [SQLITE_ERROR] result code and you would have to make a second call to +** [sqlite3_reset()] in order to find the underlying cause of the problem. +** With the "v2" prepare interfaces, the underlying reason for the error is +** returned immediately. +**
  4. +**
+** +** INVARIANTS: +** +** {F13011} The [sqlite3_prepare(db,zSql,...)] and +** [sqlite3_prepare_v2(db,zSql,...)] interfaces interpret the +** text in their zSql parameter as UTF-8. +** +** {F13012} The [sqlite3_prepare16(db,zSql,...)] and +** [sqlite3_prepare16_v2(db,zSql,...)] interfaces interpret the +** text in their zSql parameter as UTF-16 in the native byte order. +** +** {F13013} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)] +** and its variants is less than zero, then SQL text is +** read from zSql is read up to the first zero terminator. +** +** {F13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)] +** and its variants is non-negative, then nBytes bytes +** SQL text is read from zSql. +** +** {F13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants +** if the zSql input text contains more than one SQL statement +** and pzTail is not NULL, then *pzTail is made to point to the +** first byte past the end of the first SQL statement in zSql. +** What does *pzTail point to if there is one statement? +** +** {F13016} A successful call to [sqlite3_prepare_v2(db,zSql,N,ppStmt,...)] +** or one of its variants writes into *ppStmt a pointer to a new +** [prepared statement] or a pointer to NULL +** if zSql contains nothing other than whitespace or comments. +** +** {F13019} The [sqlite3_prepare_v2()] interface and its variants return +** [SQLITE_OK] or an appropriate [error code] upon failure. +*/ +int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPIREF: Retrieving Statement SQL {F13100} +** +** This intereface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement]. +** +** INVARIANTS: +** +** {F13101} If the [prepared statement] passed as +** the an argument to [sqlite3_sql()] was compiled +** compiled using either [sqlite3_prepare_v2()] or +** [sqlite3_prepare16_v2()], +** then [sqlite3_sql()] function returns a pointer to a +** zero-terminated string containing a UTF-8 rendering +** of the original SQL statement. +** +** {F13102} If the [prepared statement] passed as +** the an argument to [sqlite3_sql()] was compiled +** compiled using either [sqlite3_prepare()] or +** [sqlite3_prepare16()], +** then [sqlite3_sql()] function returns a NULL pointer. +** +** {F13103} The string returned by [sqlite3_sql(S)] is valid until the +** [prepared statement] S is deleted using [sqlite3_finalize(S)]. +*/ +const char *sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Dynamically Typed Value Object {F15000} +** +** SQLite uses the sqlite3_value object to represent all values +** that are or can be stored in a database table. +** SQLite uses dynamic typing for the values it stores. +** Values stored in sqlite3_value objects can be +** be integers, floating point values, strings, BLOBs, or NULL. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object {F16001} +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. A pointer to an sqlite3_context +** object is always first parameter to application-defined SQL functions. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements {F13500} +** +** In the SQL strings input to [sqlite3_prepare_v2()] and its +** variants, literals may be replace by a parameter in one +** of these forms: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** In the parameter forms shown above NNN is an integer literal, +** VVV alpha-numeric parameter name. +** The values of these parameters (also called "host parameter names" +** or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** The first argument to the sqlite3_bind_*() routines always +** is a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. The second +** argument is the index of the parameter to be set. The +** first parameter has an index of 1. When the same named +** parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_name()] API if desired. The index +** for "?NNN" parameters is the value of NNN. +** The NNN value must be between 1 and the compile-time +** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). +** +** The third argument is the value to bind to the parameter. +** +** In those +** routines that have a fourth argument, its value is the number of bytes +** in the parameter. To be clear: the value is the number of bytes +** in the value, not the number of characters. The number +** of bytes does not include the zero-terminator at the end of strings. +** If the fourth parameter is negative, the length of the string is +** number of bytes up to the first zero terminator. +** +** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** If the fifth argument has the value [SQLITE_TRANSIENT], then +** SQLite makes its own private copy of the data immediately, before +** the sqlite3_bind_*() routine returns. +** +** The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeros. A zeroblob uses a fixed amount of memory +** (just an integer to hold it size) while it is being processed. +** Zeroblobs are intended to serve as place-holders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | increment BLOB I/O] routines. A negative +** value for the zeroblob results in a zero-length BLOB. +** +** The sqlite3_bind_*() routines must be called after +** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and +** before [sqlite3_step()]. +** Bindings are not cleared by the [sqlite3_reset()] routine. +** Unbound parameters are interpreted as NULL. +** +** These routines return [SQLITE_OK] on success or an error code if +** anything goes wrong. [SQLITE_RANGE] is returned if the parameter +** index is out of range. [SQLITE_NOMEM] is returned if malloc fails. +** [SQLITE_MISUSE] might be returned if these routines are called on a +** virtual machine that is the wrong state or which has already been finalized. +** Detection of misuse is unreliable. Applications should not depend +** on SQLITE_MISUSE returns. SQLITE_MISUSE is intended to indicate a +** a logic error in the application. Future versions of SQLite might +** panic rather than return SQLITE_MISUSE. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13506} The [sqlite3_prepare | SQL statement compiler] recognizes +** tokens of the forms "?", "?NNN", "$VVV", ":VVV", and "@VVV" +** as SQL parameters, where NNN is any sequence of one or more +** digits and where VVV is any sequence of one or more +** alphanumeric characters or "::" optionally followed by +** a string containing no spaces and contained within parentheses. +** +** {F13509} The initial value of an SQL parameter is NULL. +** +** {F13512} The index of an "?" SQL parameter is one larger than the +** largest index of SQL parameter to the left, or 1 if +** the "?" is the leftmost SQL parameter. +** +** {F13515} The index of an "?NNN" SQL parameter is the integer NNN. +** +** {F13518} The index of an ":VVV", "$VVV", or "@VVV" SQL parameter is +** the same as the index of leftmost occurances of the same +** parameter, or one more than the largest index over all +** parameters to the left if this is the first occurrance +** of this parameter, or 1 if this is the leftmost parameter. +** +** {F13521} The [sqlite3_prepare | SQL statement compiler] fail with +** an [SQLITE_RANGE] error if the index of an SQL parameter +** is less than 1 or greater than SQLITE_MAX_VARIABLE_NUMBER. +** +** {F13524} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,V,...)] +** associate the value V with all SQL parameters having an +** index of N in the [prepared statement] S. +** +** {F13527} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,...)] +** override prior calls with the same values of S and N. +** +** {F13530} Bindings established by [sqlite3_bind_text | sqlite3_bind(S,...)] +** persist across calls to [sqlite3_reset(S)]. +** +** {F13533} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds the first L +** bytes of the blob or string pointed to by V, when L +** is non-negative. +** +** {F13536} In calls to [sqlite3_bind_text(S,N,V,L,D)] or +** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds characters +** from V through the first zero character when L is negative. +** +** {F13539} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special +** constant [SQLITE_STATIC], SQLite assumes that the value V +** is held in static unmanaged space that will not change +** during the lifetime of the binding. +** +** {F13542} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special +** constant [SQLITE_TRANSIENT], the routine makes a +** private copy of V value before it returns. +** +** {F13545} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] when D is a pointer to +** a function, SQLite invokes that function to destroy the +** V value after it has finished using the V value. +** +** {F13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound +** is a blob of L bytes, or a zero-length blob if L is negative. +*/ +int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +int sqlite3_bind_double(sqlite3_stmt*, int, double); +int sqlite3_bind_int(sqlite3_stmt*, int, int); +int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +int sqlite3_bind_null(sqlite3_stmt*, int); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of SQL Parameters {F13600} +** +** This routine can be used to find the number of SQL parameters +** in a prepared statement. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** place-holders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** This routine actually returns the index of the largest parameter. +** For all forms except ?NNN, this will correspond to the number of +** unique parameters. If parameters of the ?NNN are used, there may +** be gaps in the list. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13601} The [sqlite3_bind_parameter_count(S)] interface returns +** the largest index of all SQL parameters in the +** [prepared statement] S, or 0 if S +** contains no SQL parameters. +*/ +int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter {F13620} +** +** This routine returns a pointer to the name of the n-th +** SQL parameter in a [prepared statement]. +** SQL parameters of the form ":AAA" or "@AAA" or "$AAA" have a name +** which is the string ":AAA" or "@AAA" or "$VVV". +** In other words, the initial ":" or "$" or "@" +** is included as part of the name. +** Parameters of the form "?" or "?NNN" have no name. +** +** The first host parameter has an index of 1, not 0. +** +** If the value n is out of range or if the n-th parameter is +** nameless, then NULL is returned. The returned string is +** always in the UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13621} The [sqlite3_bind_parameter_name(S,N)] interface returns +** a UTF-8 rendering of the name of the SQL parameter in +** [prepared statement] S having index N, or +** NULL if there is no SQL parameter with index N or if the +** parameter with index N is an anonymous parameter "?" or +** a numbered parameter "?NNN". +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name {F13640} +** +** Return the index of an SQL parameter given its name. The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. A zero +** is returned if no matching parameter is found. The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13641} The [sqlite3_bind_parameter_index(S,N)] interface returns +** the index of SQL parameter in [prepared statement] +** S whose name matches the UTF-8 string N, or 0 if there is +** no match. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} +** +** Contrary to the intuition of many, [sqlite3_reset()] does not +** reset the [sqlite3_bind_blob | bindings] on a +** [prepared statement]. Use this routine to +** reset all host parameters to NULL. +** +** INVARIANTS: +** +** {F13661} The [sqlite3_clear_bindings(S)] interface resets all +** SQL parameter bindings in [prepared statement] S +** back to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set {F13710} +** +** Return the number of columns in the result set returned by the +** [prepared statement]. This routine returns 0 +** if pStmt is an SQL statement that does not return data (for +** example an UPDATE). +** +** INVARIANTS: +** +** {F13711} The [sqlite3_column_count(S)] interface returns the number of +** columns in the result set generated by the +** [prepared statement] S, or 0 if S does not generate +** a result set. +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set {F13720} +** +** These routines return the name assigned to a particular column +** in the result set of a SELECT statement. The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF16 string. The first parameter is the +** [prepared statement] that implements the SELECT statement. +** The second parameter is the column number. The left-most column is +** number 0. +** +** The returned string pointer is valid until either the +** [prepared statement] is destroyed by [sqlite3_finalize()] +** or until the next call sqlite3_column_name() or sqlite3_column_name16() +** on the same column. +** +** If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +** +** INVARIANTS: +** +** {F13721} A successful invocation of the [sqlite3_column_name(S,N)] +** interface returns the name +** of the Nth column (where 0 is the left-most column) for the +** result set of [prepared statement] S as a +** zero-terminated UTF-8 string. +** +** {F13723} A successful invocation of the [sqlite3_column_name16(S,N)] +** interface returns the name +** of the Nth column (where 0 is the left-most column) for the +** result set of [prepared statement] S as a +** zero-terminated UTF-16 string in the native byte order. +** +** {F13724} The [sqlite3_column_name()] and [sqlite3_column_name16()] +** interfaces return a NULL pointer if they are unable to +** allocate memory memory to hold there normal return strings. +** +** {F13725} If the N parameter to [sqlite3_column_name(S,N)] or +** [sqlite3_column_name16(S,N)] is out of range, then the +** interfaces returns a NULL pointer. +** +** {F13726} The strings returned by [sqlite3_column_name(S,N)] and +** [sqlite3_column_name16(S,N)] are valid until the next +** call to either routine with the same S and N parameters +** or until [sqlite3_finalize(S)] is called. +** +** {F13727} When a result column of a [SELECT] statement contains +** an AS clause, the name of that column is the indentifier +** to the right of the AS keyword. +*/ +const char *sqlite3_column_name(sqlite3_stmt*, int N); +const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result {F13740} +** +** These routines provide a means to determine what column of what +** table in which database a result of a SELECT statement comes from. +** The name of the database or table or column can be returned as +** either a UTF8 or UTF16 string. The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** The returned string is valid until +** the [prepared statement] is destroyed using +** [sqlite3_finalize()] or until the same information is requested +** again in a different encoding. +** +** The names returned are the original un-aliased names of the +** database, table, and column. +** +** The first argument to the following calls is a [prepared statement]. +** These functions return information about the Nth column returned by +** the statement, where N is the second function argument. +** +** If the Nth column returned by the statement is an expression +** or subquery and is not a column value, then all of these functions +** return NULL. These routine might also return NULL if a memory +** allocation error occurs. Otherwise, they return the +** name of the attached database, table and column that query result +** column was extracted from. +** +** As with all other SQLite APIs, those postfixed with "16" return +** UTF-16 encoded strings, the other functions return UTF-8. {END} +** +** These APIs are only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +** +** {U13751} +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. +** +** INVARIANTS: +** +** {F13741} The [sqlite3_column_database_name(S,N)] interface returns either +** the UTF-8 zero-terminated name of the database from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13742} The [sqlite3_column_database_name16(S,N)] interface returns either +** the UTF-16 native byte order +** zero-terminated name of the database from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13743} The [sqlite3_column_table_name(S,N)] interface returns either +** the UTF-8 zero-terminated name of the table from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13744} The [sqlite3_column_table_name16(S,N)] interface returns either +** the UTF-16 native byte order +** zero-terminated name of the table from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13745} The [sqlite3_column_origin_name(S,N)] interface returns either +** the UTF-8 zero-terminated name of the table column from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13746} The [sqlite3_column_origin_name16(S,N)] interface returns either +** the UTF-16 native byte order +** zero-terminated name of the table column from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13748} The return values from +** [sqlite3_column_database_name|column metadata interfaces] +** are valid +** for the lifetime of the [prepared statement] +** or until the encoding is changed by another metadata +** interface call for the same prepared statement and column. +** +** LIMITATIONS: +** +** {U13751} If two or more threads call one or more +** [sqlite3_column_database_name|column metadata interfaces] +** the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +const char *sqlite3_column_database_name(sqlite3_stmt*,int); +const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +const char *sqlite3_column_table_name(sqlite3_stmt*,int); +const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result {F13760} +** +** The first parameter is a [prepared statement]. +** If this statement is a SELECT statement and the Nth column of the +** returned result set of that SELECT is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned. If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** The returned string is always UTF-8 encoded. {END} +** For example, in the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** And the following statement compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** Then this routine would return the string "VARIANT" for the second +** result column (i==1), and a NULL pointer for the first result column +** (i==0). +** +** SQLite uses dynamic run-time typing. So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. Type +** is associated with individual values, not with the containers +** used to hold those values. +** +** INVARIANTS: +** +** {F13761} A successful call to [sqlite3_column_decltype(S,N)] +** returns a zero-terminated UTF-8 string containing the +** the declared datatype of the table column that appears +** as the Nth column (numbered from 0) of the result set to the +** [prepared statement] S. +** +** {F13762} A successful call to [sqlite3_column_decltype16(S,N)] +** returns a zero-terminated UTF-16 native byte order string +** containing the declared datatype of the table column that appears +** as the Nth column (numbered from 0) of the result set to the +** [prepared statement] S. +** +** {F13763} If N is less than 0 or N is greater than or equal to +** the number of columns in [prepared statement] S +** or if the Nth column of S is an expression or subquery rather +** than a table column or if a memory allocation failure +** occurs during encoding conversions, then +** calls to [sqlite3_column_decltype(S,N)] or +** [sqlite3_column_decltype16(S,N)] return NULL. +*/ +const char *sqlite3_column_decltype(sqlite3_stmt*,int); +const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement {F13200} +** +** After an [prepared statement] has been prepared with a call +** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of +** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], +** then this function must be called one or more times to evaluate the +** statement. +** +** The details of the behavior of this sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** In the lagacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** With the "v2" interface, any of the other [SQLITE_OK | result code] +** or [SQLITE_IOERR_READ | extended result code] might be returned as +** well. +** +** [SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. If the statement is a COMMIT +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a COMMIT and occurs within a +** explicit transaction then you should rollback the transaction before +** continuing. +** +** [SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** If the SQL statement being executed returns any data, then +** [SQLITE_ROW] is returned each time a new row of data is ready +** for processing by the caller. The values may be accessed using +** the [sqlite3_column_int | column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** [SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** With the legacy interface, a more specific error code (example: +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** Goofy Interface Alert: +** In the legacy interface, +** the sqlite3_step() API always returns a generic error code, +** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] +** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or +** [sqlite3_finalize()] in order to find one of the specific +** [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the +** more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +** +** INVARIANTS: +** +** {F13202} If [prepared statement] S is ready to be +** run, then [sqlite3_step(S)] advances that prepared statement +** until to completion or until it is ready to return another +** row of the result set or an interrupt or run-time error occurs. +** +** {F15304} When a call to [sqlite3_step(S)] causes the +** [prepared statement] S to run to completion, +** the function returns [SQLITE_DONE]. +** +** {F15306} When a call to [sqlite3_step(S)] stops because it is ready +** to return another row of the result set, it returns +** [SQLITE_ROW]. +** +** {F15308} If a call to [sqlite3_step(S)] encounters an +** [sqlite3_interrupt|interrupt] or a run-time error, +** it returns an appropraite error code that is not one of +** [SQLITE_OK], [SQLITE_ROW], or [SQLITE_DONE]. +** +** {F15310} If an [sqlite3_interrupt|interrupt] or run-time error +** occurs during a call to [sqlite3_step(S)] +** for a [prepared statement] S created using +** legacy interfaces [sqlite3_prepare()] or +** [sqlite3_prepare16()] then the function returns either +** [SQLITE_ERROR], [SQLITE_BUSY], or [SQLITE_MISUSE]. +*/ +int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set {F13770} +** +** Return the number of values in the current row of the result set. +** +** INVARIANTS: +** +** {F13771} After a call to [sqlite3_step(S)] that returns +** [SQLITE_ROW], the [sqlite3_data_count(S)] routine +** will return the same value as the +** [sqlite3_column_count(S)] function. +** +** {F13772} After [sqlite3_step(S)] has returned any value other than +** [SQLITE_ROW] or before [sqlite3_step(S)] has been +** called on the [prepared statement] for +** the first time since it was [sqlite3_prepare|prepared] +** or [sqlite3_reset|reset], the [sqlite3_data_count(S)] +** routine returns zero. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes {F10265} +** KEYWORDS: SQLITE_TEXT +** +** {F10266}Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
{END} +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Results Values From A Query {F13800} +** +** These routines form the "result set query" interface. +** +** These routines return information about +** a single column of the current result row of a query. In every +** case the first argument is a pointer to the +** [prepared statement] that is being +** evaluated (the [sqlite3_stmt*] that was returned from +** [sqlite3_prepare_v2()] or one of its variants) and +** the second argument is the index of the column for which information +** should be returned. The left-most column of the result set +** has an index of 0. +** +** If the SQL statement is not currently point to a valid row, or if the +** the column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** The sqlite3_column_type() routine returns +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** The value returned does not include the zero terminator at the end +** of the string. For clarity: the value returned is the number of +** bytes in the string, not the number of characters. +** +** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero terminated. The return +** value from sqlite3_column_blob() for a zero-length blob is an arbitrary +** pointer, possibly even a NULL pointer. +** +** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() +** but leaves the result in UTF-16 in native byte order instead of UTF-8. +** The zero terminator is not included in this count. +** +** These routines attempt to convert the value where appropriate. For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to do the conversion +** automatically. The following table details the conversions that +** are applied: +** +**
+** +**
Internal
Type
Requested
Type
Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is NULL pointer +**
NULL BLOB Result is NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as for INTEGER->TEXT +**
FLOAT INTEGER Convert from float to integer +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB Same as FLOAT->TEXT +**
TEXT INTEGER Use atoi() +**
TEXT FLOAT Use atof() +**
TEXT BLOB No change +**
BLOB INTEGER Convert to TEXT then use atoi() +**
BLOB FLOAT Convert to TEXT then use atof() +**
BLOB TEXT Add a zero terminator if needed +**
+**
+** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** on equavalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
    +**
  • The initial content is a BLOB and sqlite3_column_text() +** or sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.

  • +** +**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.

  • +** +**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.

  • +**
+** +** Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer points to will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometime it is +** not possible and in those cases prior pointers are invalidated. +** +** The safest and easiest to remember policy is to invoke these routines +** in one of the following ways: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), +** or sqlite3_column_text16() first to force the result into the desired +** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to +** find the size of the result. Do not mix call to sqlite3_column_text() or +** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not +** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). +** +** The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. The memory space used to hold strings +** and blobs is freed automatically. Do not pass the pointers returned +** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM]. +** +** INVARIANTS: +** +** {F13803} The [sqlite3_column_blob(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a blob and then returns a +** pointer to the converted value. +** +** {F13806} The [sqlite3_column_bytes(S,N)] interface returns the +** number of bytes in the blob or string (exclusive of the +** zero terminator on the string) that was returned by the +** most recent call to [sqlite3_column_blob(S,N)] or +** [sqlite3_column_text(S,N)]. +** +** {F13809} The [sqlite3_column_bytes16(S,N)] interface returns the +** number of bytes in the string (exclusive of the +** zero terminator on the string) that was returned by the +** most recent call to [sqlite3_column_text16(S,N)]. +** +** {F13812} The [sqlite3_column_double(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a floating point value and +** returns a copy of that value. +** +** {F13815} The [sqlite3_column_int(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a 32-bit signed integer and +** returns a copy of that integer. +** +** {F13818} The [sqlite3_column_int64(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a 64-bit signed integer and +** returns a copy of that integer. +** +** {F13821} The [sqlite3_column_text(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a zero-terminated UTF-8 +** string and returns a pointer to that string. +** +** {F13824} The [sqlite3_column_text16(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a zero-terminated 2-byte +** aligned UTF-16 native byte order +** string and returns a pointer to that string. +** +** {F13827} The [sqlite3_column_type(S,N)] interface returns +** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT], +** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for +** the Nth column in the current row of the result set for +** [prepared statement] S. +** +** {F13830} The [sqlite3_column_value(S,N)] interface returns a +** pointer to the [sqlite3_value] object that for the +** Nth column in the current row of the result set for +** [prepared statement] S. +*/ +const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +double sqlite3_column_double(sqlite3_stmt*, int iCol); +int sqlite3_column_int(sqlite3_stmt*, int iCol); +sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +int sqlite3_column_type(sqlite3_stmt*, int iCol); +sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object {F13300} +** +** The sqlite3_finalize() function is called to delete a +** [prepared statement]. If the statement was +** executed successfully, or not executed at all, then SQLITE_OK is returned. +** If execution of the statement failed then an +** [error code] or [extended error code] +** is returned. +** +** This routine can be called at any point during the execution of the +** [prepared statement]. If the virtual machine has not +** completed execution when this routine is called, that is like +** encountering an error or an interrupt. (See [sqlite3_interrupt()].) +** Incomplete updates may be rolled back and transactions cancelled, +** depending on the circumstances, and the +** [error code] returned will be [SQLITE_ABORT]. +** +** INVARIANTS: +** +** {F11302} The [sqlite3_finalize(S)] interface destroys the +** [prepared statement] S and releases all +** memory and file resources held by that object. +** +** {F11304} If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned an error, +** then [sqlite3_finalize(S)] returns that same error. +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object {F13330} +** +** The sqlite3_reset() function is called to reset a +** [prepared statement] object. +** back to its initial state, ready to be re-executed. +** Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** {F11332} The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** {F11334} If the most recent call to [sqlite3_step(S)] for +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** {F11336} If the most recent call to [sqlite3_step(S)] for +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** {F11338} The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on [prepared statement] S. +*/ +int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions {F16100} +** KEYWORDS: {function creation routines} +** +** These two functions (collectively known as +** "function creation routines") are used to add SQL functions or aggregates +** or to redefine the behavior of existing SQL functions or aggregates. The +** difference only between the two is that the second parameter, the +** name of the (scalar) function or aggregate, is encoded in UTF-8 for +** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). +** +** The first argument is the [database connection] that holds the +** SQL function or aggregate is to be added or redefined. If a single +** program uses more than one database handle internally, then SQL +** functions or aggregates must be added individually to each database +** handle with which they will be used. +** +** The second parameter is the name of the SQL function to be created +** or redefined. +** The length of the name is limited to 255 bytes, exclusive of the +** zero-terminator. Note that the name length limit is in bytes, not +** characters. Any attempt to create a function with a longer name +** will result in an SQLITE_ERROR error. +** +** The third parameter is the number of arguments that the SQL function or +** aggregate takes. If this parameter is negative, then the SQL function or +** aggregate may take any number of arguments. +** +** The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Any SQL function implementation should be able to work +** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. It is allowed to +** invoke sqlite3_create_function() or sqlite3_create_function16() multiple +** times with the same function but with different values of eTextRep. +** When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** If there is only a single implementation which does not care what +** text encoding is used, then the fourth argument should be +** [SQLITE_ANY]. +** +** The fifth parameter is an arbitrary pointer. The implementation +** of the function can gain access to this pointer using +** [sqlite3_user_data()]. +** +** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL +** function or aggregate. A scalar SQL function requires an implementation of +** the xFunc callback only, NULL pointers should be passed as the xStep +** and xFinal parameters. An aggregate SQL function requires an implementation +** of xStep and xFinal and NULL should be passed for xFunc. To delete an +** existing SQL function or aggregate, pass NULL for all three function +** callback. +** +** It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing perferred text encodings. SQLite will use +** the implementation most closely matches the way in which the +** SQL function is used. +** +** INVARIANTS: +** +** {F16103} The [sqlite3_create_function16()] interface behaves exactly +** like [sqlite3_create_function()] in every way except that it +** interprets the zFunctionName argument as +** zero-terminated UTF-16 native byte order instead of as a +** zero-terminated UTF-8. +** +** {F16106} +*/ +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); + +/* +** CAPI3REF: Text Encodings {F10267} +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Obsolete Functions +** +** These functions are all now obsolete. In order to maintain +** backwards compatibility with older code, we continue to support +** these functions. However, new development projects should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you want they do. +*/ +int sqlite3_aggregate_count(sqlite3_context*); +int sqlite3_expired(sqlite3_stmt*); +int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +int sqlite3_global_recover(void); +void sqlite3_thread_cleanup(void); +int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 4th parameter to these callbacks is an array of pointers to +** [sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work just like the corresponding +** [sqlite3_column_blob | sqlite3_column_* routines] except that +** these routines take a single [sqlite3_value*] pointer instead +** of an [sqlite3_stmt*] pointer and an integer column number. +** +** The sqlite3_value_text16() interface extracts a UTF16 string +** in the native byte-order of the host machine. The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF16 strings as big-endian and little-endian respectively. +** +** The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words if the value is a string that looks like a number) +** then the conversion is done. Otherwise no conversion occurs. The +** [SQLITE_INTEGER | datatype] after conversion is returned. +** +** Please pay particular attention to the fact that the pointer that +** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the sqlite3_value* parameters. +** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] +** interface, then these routines should be called from the same thread +** that ran [sqlite3_column_value()]. +** +*/ +const void *sqlite3_value_blob(sqlite3_value*); +int sqlite3_value_bytes(sqlite3_value*); +int sqlite3_value_bytes16(sqlite3_value*); +double sqlite3_value_double(sqlite3_value*); +int sqlite3_value_int(sqlite3_value*); +sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +const unsigned char *sqlite3_value_text(sqlite3_value*); +const void *sqlite3_value_text16(sqlite3_value*); +const void *sqlite3_value_text16le(sqlite3_value*); +const void *sqlite3_value_text16be(sqlite3_value*); +int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context {F16210} +** +** The implementation of aggregate SQL functions use this routine to allocate +** a structure for storing their state. +** {F16211} The first time the sqlite3_aggregate_context() routine is +** is called for a particular aggregate, SQLite allocates nBytes of memory +** zeros that memory, and returns a pointer to it. +** {F16212} On second and subsequent calls to sqlite3_aggregate_context() +** for the same aggregate function index, the same buffer is returned. {END} +** The implementation +** of the aggregate can use the returned buffer to accumulate data. +** +** {F16213} SQLite automatically frees the allocated buffer when the aggregate +** query concludes. {END} +** +** The first parameter should be a copy of the +** [sqlite3_context | SQL function context] that is the first +** parameter to the callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions {F16240} +** +** {F16241} The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. {END} +** +** {U16243} This routine must be called from the same thread in which +** the application-defined function is running. +*/ +void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data {F16270} +** +** The following two functions may be used by scalar SQL functions to +** associate meta-data with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated meta-data may be preserved. This may +** be used, for example, to add a regular-expression matching scalar +** function. The compiled version of the regular expression is stored as +** meta-data associated with the SQL value passed as the regular expression +** pattern. The compiled regular expression can be reused on multiple +** invocations of the same function so that the original pattern string +** does not need to be recompiled on each invocation. +** +** {F16271} +** The sqlite3_get_auxdata() interface returns a pointer to the meta-data +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. +** {F16272} If no meta-data has been ever been set for the Nth +** argument of the function, or if the cooresponding function parameter +** has changed since the meta-data was set, then sqlite3_get_auxdata() +** returns a NULL pointer. +** +** {F16275} The sqlite3_set_auxdata() interface saves the meta-data +** pointed to by its 3rd parameter as the meta-data for the N-th +** argument of the application-defined function. {END} Subsequent +** calls to sqlite3_get_auxdata() might return this data, if it has +** not been destroyed. +** {F16277} If it is not NULL, SQLite will invoke the destructor +** function given by the 4th parameter to sqlite3_set_auxdata() on +** the meta-data when the corresponding function parameter changes +** or when the SQL statement completes, whichever comes first. {END} +** +** In practice, meta-data is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and SQL variables. +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +void *sqlite3_get_auxdata(sqlite3_context*, int N); +void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} +** +** These are special value for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. See ticket #2191. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function {F16400} +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the +** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used +** to bind values to host parameters in prepared statements. +** Refer to the +** [sqlite3_bind_blob | sqlite3_bind_* documentation] for +** additional information. +** +** {F16402} The sqlite3_result_blob() interface sets the result from +** an application defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of +** the application defined function to be a BLOB containing all zero +** bytes and N bytes in size, where N is the value of the 2nd parameter. +** +** {F16407} The sqlite3_result_double() interface sets the result from +** an application defined function to be a floating point value specified +** by its 2nd argument. +** +** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** {F16411} SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. {F16412} SQLite interprets the error +** message string from sqlite3_result_error() as UTF8. {F16413} SQLite +** interprets the string from sqlite3_result_error16() as UTF16 in native +** byte order. {F16414} If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** {F16415} If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** {F16417} The sqlite3_result_error() and sqlite3_result_error16() +** routines make a copy private copy of the error message text before +** they return. {END} Hence, the calling function can deallocate or +** modify the text after they return without harm. +** The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. By default, +** the error code is SQLITE_ERROR. +** +** {F16421} The sqlite3_result_toobig() interface causes SQLite +** to throw an error indicating that a string or BLOB is to long +** to represent. {F16422} The sqlite3_result_nomem() interface +** causes SQLite to throw an exception indicating that the a +** memory allocation failed. +** +** {F16431} The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** {F16432} The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** {F16437} The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** {F16442} SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. +** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or blob result when it has +** finished using that result. +** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_STATIC, then +** SQLite assumes that the text or blob result is constant space and +** does not copy the space or call a destructor when it has +** finished using that result. +** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained from +** from [sqlite3_malloc()] before it returns. +** +** {F16461} The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy the [sqlite3_value] +** object specified by the 2nd parameter. {F16463} The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** +** {U16491} These routines are called from within the different thread +** than the one containing the application-defined function that recieved +** the [sqlite3_context] pointer, the results are undefined. +*/ +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_double(sqlite3_context*, double); +void sqlite3_result_error(sqlite3_context*, const char*, int); +void sqlite3_result_error16(sqlite3_context*, const void*, int); +void sqlite3_result_error_toobig(sqlite3_context*); +void sqlite3_result_error_nomem(sqlite3_context*); +void sqlite3_result_error_code(sqlite3_context*, int); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences {F16600} +** +** {F16601} +** These functions are used to add new collation sequences to the +** [sqlite3*] handle specified as the first argument. +** +** {F16602} +** The name of the new collation sequence is specified as a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases +** the name is passed as the second function argument. +** +** {F16604} +** The third argument may be one of the constants [SQLITE_UTF8], +** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied +** routine expects to be passed pointers to strings encoded using UTF-8, +** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The +** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that +** the routine expects pointers to 16-bit word aligned strings +** of UTF16 in the native byte order of the host computer. +** +** {F16607} +** A pointer to the user supplied routine must be passed as the fifth +** argument. {F16609} If it is NULL, this is the same as deleting the collation +** sequence (so that SQLite cannot call it anymore). +** {F16611} Each time the application +** supplied function is invoked, it is passed a copy of the void* passed as +** the fourth argument to sqlite3_create_collation() or +** sqlite3_create_collation16() as its first parameter. +** +** {F16612} +** The remaining arguments to the application-supplied routine are two strings, +** each represented by a (length, data) pair and encoded in the encoding +** that was passed as the third argument when the collation sequence was +** registered. {END} The application defined collation routine should +** return negative, zero or positive if +** the first string is less than, equal to, or greater than the second +** string. i.e. (STRING1 - STRING2). +** +** {F16615} +** The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** excapt that it takes an extra argument which is a destructor for +** the collation. {F16617} The destructor is called when the collation is +** destroyed and is passed a copy of the fourth parameter void* pointer +** of the sqlite3_create_collation_v2(). +** {F16618} Collations are destroyed when +** they are overridden by later calls to the collation creation functions +** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. +*/ +int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); +int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +int sqlite3_create_collation16( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks {F16700} +** +** {F16701} +** To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** database handle to be called whenever an undefined collation sequence is +** required. +** +** {F16702} +** If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names +** are passed as UTF-16 in machine native byte order. {F16704} A call to either +** function replaces any existing callback. +** +** {F16705} When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). {F16706} The second argument is the database +** handle. {F16707} The third argument is one of [SQLITE_UTF8], +** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most +** desirable form of the collation sequence function required. +** {F16708} The fourth parameter is the name of the +** required collation sequence. {END} +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +/* +** CAPI3REF: Suspend Execution For A Short Time {F10530} +** +** {F10531} The sqlite3_sleep() function +** causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** {F10532} If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. {F10533} The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** {F10534} SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. {END} +*/ +int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} +** +** If this global variable is made to point to a string which is +** the name of a folder (a.ka. directory), then all temporary files +** created by SQLite will be placed in that directory. If this variable +** is NULL pointer, then SQLite does a search for an appropriate temporary +** file directory. +** +** It is not safe to modify this variable once a database connection +** has been opened. It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been call and remain unchanged thereafter. +*/ +SQLITE_EXTERN char *sqlite3_temp_directory; + +/* +** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} +** +** The sqlite3_get_autocommit() interfaces returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. Autocommit mode is on +** by default. Autocommit mode is disabled by a [BEGIN] statement. +** Autocommit mode is reenabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out if SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** INVARIANTS: +** +** {F12931} The [sqlite3_get_autocommit()] interface returns non-zero or +** zero if the given database connection is or is not in autocommit +** mode, respectively. +** +** {F12932} Autocommit mode is on by default. +** +** {F12933} Autocommit mode is disabled by a successful [BEGIN] statement. +** +** {F12934} Autocommit mode is enabled by a successful [COMMIT] or [ROLLBACK] +** statement. +** +** +** LIMITATIONS: +*** +** {U12936} If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} +** +** {F13121} The sqlite3_db_handle interface +** returns the [sqlite3*] database handle to which a +** [prepared statement] belongs. +** {F13122} the database handle returned by sqlite3_db_handle +** is the same database handle that was +** the first argument to the [sqlite3_prepare_v2()] or its variants +** that was used to create the statement in the first place. +*/ +sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} +** +** {F12951} The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is committed. +** {F12952} Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** {F12953} The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is committed. +** {F12954} Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** {F12956} The pArg argument is passed through +** to the callback. {F12957} If the callback on a commit hook function +** returns non-zero, then the commit is converted into a rollback. +** +** {F12958} If another function was previously registered, its +** pArg value is returned. Otherwise NULL is returned. +** +** {F12959} Registering a NULL function disables the callback. +** +** {F12961} For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** {F12962} The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** {F12964} The rollback callback is not invoked if a transaction is +** rolled back because a commit callback returned non-zero. +** Check on this {END} +** +** These are experimental interfaces and are subject to change. +*/ +void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks {F12970} +** +** {F12971} The sqlite3_update_hook() interface +** registers a callback function with the database connection identified by the +** first argument to be invoked whenever a row is updated, inserted or deleted. +** {F12972} Any callback set by a previous call to this function for the same +** database connection is overridden. +** +** {F12974} The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. +** {F12976} The first argument to the callback is +** a copy of the third argument to sqlite3_update_hook(). +** {F12977} The second callback +** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], +** depending on the operation that caused the callback to be invoked. +** {F12978} The third and +** fourth arguments to the callback contain pointers to the database and +** table name containing the affected row. +** {F12979} The final callback parameter is +** the rowid of the row. +** {F12981} In the case of an update, this is the rowid after +** the update takes place. +** +** {F12983} The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence). +** +** {F12984} If another function was previously registered, its pArg value +** is returned. {F12985} Otherwise NULL is returned. +*/ +void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} +** +** {F10331} +** This routine enables or disables the sharing of the database cache +** and schema data structures between connections to the same database. +** {F10332} +** Sharing is enabled if the argument is true and disabled if the argument +** is false. +** +** {F10333} Cache sharing is enabled and disabled +** for an entire process. {END} This is a change as of SQLite version 3.5.0. +** In prior versions of SQLite, sharing was +** enabled or disabled for each thread separately. +** +** {F10334} +** The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** {F10335} Existing database connections continue use the sharing mode +** that was in effect at the time they were opened. {END} +** +** Virtual tables cannot be used with a shared cache. {F10336} When shared +** cache is enabled, the [sqlite3_create_module()] API used to register +** virtual tables will always return an error. {END} +** +** {F10337} This routine returns [SQLITE_OK] if shared cache was +** enabled or disabled successfully. {F10338} An [error code] +** is returned otherwise. {END} +** +** {F10339} Shared cache is disabled by default. {END} But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +*/ +int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory {F17340} +** +** {F17341} The sqlite3_release_memory() interface attempts to +** free N bytes of heap memory by deallocating non-essential memory +** allocations held by the database labrary. {END} Memory used +** to cache database pages to improve performance is an example of +** non-essential memory. {F16342} sqlite3_release_memory() returns +** the number of bytes actually freed, which might be more or less +** than the amount requested. +*/ +int sqlite3_release_memory(int); + +/* +** CAPI3REF: Impose A Limit On Heap Size {F17350} +** +** {F16351} The sqlite3_soft_heap_limit() interface +** places a "soft" limit on the amount of heap memory that may be allocated +** by SQLite. {F16352} If an internal allocation is requested +** that would exceed the soft heap limit, [sqlite3_release_memory()] is +** invoked one or more times to free up some space before the allocation +** is made. {END} +** +** {F16353} The limit is called "soft", because if +** [sqlite3_release_memory()] cannot +** free sufficient memory to prevent the limit from being exceeded, +** the memory is allocated anyway and the current operation proceeds. +** +** {F16354} +** A negative or zero value for N means that there is no soft heap limit and +** [sqlite3_release_memory()] will only be called when memory is exhausted. +** {F16355} The default value for the soft heap limit is zero. +** +** SQLite makes a best effort to honor the soft heap limit. +** {F16356} But if the soft heap limit cannot honored, execution will +** continue without error or notification. {END} This is why the limit is +** called a "soft" limit. It is advisory only. +** +** Prior to SQLite version 3.5.0, this routine only constrained the memory +** allocated by a single thread - the same thread in which this routine +** runs. Beginning with SQLite version 3.5.0, the soft heap limit is +** applied to all threads. {F16357} The value specified for the soft heap limit +** is an upper bound on the total memory allocation for all threads. {END} In +** version 3.5.0 there is no mechanism for limiting the heap usage for +** individual threads. +*/ +void sqlite3_soft_heap_limit(int); + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} +** +** This routine +** returns meta-data about a specific column of a specific database +** table accessible using the connection handle passed as the first function +** argument. +** +** The column is identified by the second, third and fourth parameters to +** this function. The second parameter is either the name of the database +** (i.e. "main", "temp" or an attached database) containing the specified +** table or NULL. If it is NULL, then all attached databases are searched +** for the table using the same algorithm as the database engine uses to +** resolve unqualified table references. +** +** The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** Meta information is returned by writing to the memory locations passed as +** the 5th and subsequent parameters to this function. Any of these +** arguments may be NULL, in which case the corresponding element of meta +** information is ommitted. +** +**
+** Parameter     Output Type      Description
+** -----------------------------------
+**
+**   5th         const char*      Data type
+**   6th         const char*      Name of the default collation sequence 
+**   7th         int              True if the column has a NOT NULL constraint
+**   8th         int              True if the column is part of the PRIMARY KEY
+**   9th         int              True if the column is AUTOINCREMENT
+** 
+** +** +** The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any sqlite API function. +** +** If the specified table is actually a view, then an error is returned. +** +** If the specified column is "rowid", "oid" or "_rowid_" and an +** INTEGER PRIMARY KEY column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. If there is no +** explicitly declared IPK column, then the output parameters are set as +** follows: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
+** +** This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an SQLITE error code is returned and an error message +** left in the database handle (to be retrieved using sqlite3_errmsg()). +** +** This API is only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension {F12600} +** +** {F12601} The sqlite3_load_extension() interface +** attempts to load an SQLite extension library contained in the file +** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 +** in which case the name of the entry point defaults +** to "sqlite3_extension_init". +** +** {F12604} The sqlite3_load_extension() interface shall +** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** +** {F12605} +** If an error occurs and pzErrMsg is not 0, then the +** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with +** error message text stored in memory obtained from [sqlite3_malloc()]. +** {END} The calling function should free this memory +** by calling [sqlite3_free()]. +** +** {F12606} +** Extension loading must be enabled using [sqlite3_enable_load_extension()] +** prior to calling this API or an error will be returned. +*/ +int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading {F12620} +** +** So as not to open security holes in older applications that are +** unprepared to deal with extension loading, and as a means of disabling +** extension loading while evaluating user-entered SQL, the following +** API is provided to turn the [sqlite3_load_extension()] mechanism on and +** off. {F12622} It is off by default. {END} See ticket #1863. +** +** {F12621} Call the sqlite3_enable_load_extension() routine +** with onoff==1 to turn extension loading on +** and call it with onoff==0 to turn it back off again. {END} +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} +** +** {F12641} This function +** registers an extension entry point that is automatically invoked +** whenever a new database connection is opened using +** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} +** +** This API can be invoked at program startup in order to register +** one or more statically linked extensions that will be available +** to all new database connections. +** +** {F12642} Duplicate extensions are detected so calling this routine multiple +** times with the same extension is harmless. +** +** {F12643} This routine stores a pointer to the extension in an array +** that is obtained from sqlite_malloc(). {END} If you run a memory leak +** checker on your program and it reports a leak because of this +** array, then invoke [sqlite3_reset_auto_extension()] prior +** to shutdown to free the memory. +** +** {F12644} Automatic extensions apply across all threads. {END} +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +int sqlite3_auto_extension(void *xEntryPoint); + + +/* +** CAPI3REF: Reset Automatic Extension Loading {F12660} +** +** {F12661} This function disables all previously registered +** automatic extensions. {END} This +** routine undoes the effect of all prior [sqlite3_auto_extension()] +** calls. +** +** {F12662} This call disabled automatic extensions in all threads. {END} +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +void sqlite3_reset_auto_extension(void); + + +/* +****** EXPERIMENTAL - subject to change without notice ************** +** +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stablizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** A module is a class of virtual tables. Each module is defined +** by an instance of the following structure. This structure consists +** mostly of methods for the module. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); +}; + +/* +** The sqlite3_index_info structure and its substructures is used to +** pass information into and receive the reply from the xBestIndex +** method of an sqlite3_module. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** The aConstraint[] array records WHERE clause constraints of the +** form: +** +** column OP expr +** +** Where OP is =, <, <=, >, or >=. +** The particular operator is stored +** in aConstraint[].op. The index of the column is stored in +** aConstraint[].iColumn. aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot. +** +** The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** The aConstraint[] array only reports WHERE clause terms in the correct +** form that refer to the particular virtual table being queried. +** +** Information about the ORDER BY clause is stored in aOrderBy[]. +** Each term of aOrderBy records a column of the ORDER BY clause. +** +** The xBestIndex method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite. +** +** The idxNum and idxPtr values are recorded and passed into xFilter. +** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from xFilter will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** The estimatedCost value is an estimate of the cost of doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +*/ +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ +}; +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** This routine is used to register a new module name with an SQLite +** connection. Module names must be registered before creating new +** virtual tables on the module, or before using preexisting virtual +** tables of the module. +*/ +int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void * /* Client data for xCreate/xConnect */ +); + +/* +** This routine is identical to the sqlite3_create_module() method above, +** except that it allows a destructor function to be specified. It is +** even more experimental than the rest of the virtual tables API. +*/ +int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void *, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** Every module implementation uses a subclass of the following structure +** to describe a particular instance of the module. Each subclass will +** be tailored to the specific needs of the module implementation. The +** purpose of this superclass is to define certain fields that are common +** to all module implementations. +** +** Virtual tables methods can set an error message by assigning a +** string obtained from sqlite3_mprintf() to zErrMsg. The method should +** take care that any prior string is freed by a call to sqlite3_free() +** prior to assigning a new string to zErrMsg. After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note +** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field +** since virtual tables are commonly implemented in loadable extensions which +** do not have access to sqlite3MPrintf() or sqlite3Free(). +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Used internally */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* Every module implementation uses a subclass of the following structure +** to describe cursors that point into the virtual table and are used +** to loop through the virtual table. Cursors are created using the +** xOpen method of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** The xCreate and xConnect methods of a module use the following API +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); + +/* +** Virtual tables can provide alternative implementations of functions +** using the xFindFunction method. But global versions of those functions +** must exist in order to be overloaded. +** +** This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created. The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a place-holder function that can be overloaded +** by virtual tables. +** +** This API should be considered part of the virtual table interface, +** which is experimental and subject to change. +*/ +int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +** +****** EXPERIMENTAL - subject to change without notice ************** +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB {F17800} +** +** An instance of the following opaque structure is used to +** represent an blob-handle. A blob-handle is created by +** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. +** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the blob. +** The [sqlite3_blob_bytes()] interface returns the size of the +** blob in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O {F17810} +** +** {F17811} This interfaces opens a handle to the blob located +** in row iRow,, column zColumn, table zTable in database zDb; +** in other words, the same blob that would be selected by: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
+** 
{END} +** +** {F17812} If the flags parameter is non-zero, the blob is opened for +** read and write access. If it is zero, the blob is opened for read +** access. {END} +** +** {F17813} On success, [SQLITE_OK] is returned and the new +** [sqlite3_blob | blob handle] is written to *ppBlob. +** {F17814} Otherwise an error code is returned and +** any value written to *ppBlob should not be used by the caller. +** {F17815} This function sets the database-handle error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** We should go through and mark all interfaces that behave this +** way with a similar statement +*/ +int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Close A BLOB Handle {F17830} +** +** Close an open [sqlite3_blob | blob handle]. +** +** {F17831} Closing a BLOB shall cause the current transaction to commit +** if there are no other BLOBs, no pending prepared statements, and the +** database connection is in autocommit mode. +** {F17832} If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. {END} +** Closing the BLOB often forces the changes +** out to disk and so if any I/O errors occur, they will likely occur +** at the time when the BLOB is closed. {F17833} Any errors that occur during +** closing are reported as a non-zero return value. +** +** {F17839} The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed. +*/ +int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB {F17805} +** +** {F16806} Return the size in bytes of the blob accessible via the open +** [sqlite3_blob | blob-handle] passed as an argument. +*/ +int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally {F17850} +** +** This function is used to read data from an open +** [sqlite3_blob | blob-handle] into a caller supplied buffer. +** {F17851} n bytes of data are copied into buffer +** z from the open blob, starting at offset iOffset. +** +** {F17852} If offset iOffset is less than n bytes from the end of the blob, +** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is +** less than zero [SQLITE_ERROR] is returned and no data is read. +** +** {F17854} On success, SQLITE_OK is returned. Otherwise, an +** [error code] or an [extended error code] is returned. +*/ +int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} +** +** This function is used to write data into an open +** [sqlite3_blob | blob-handle] from a user supplied buffer. +** {F17871} n bytes of data are copied from the buffer +** pointed to by z into the open blob, starting at offset iOffset. +** +** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument +** was not opened for writing (the flags parameter to [sqlite3_blob_open()] +*** was zero), this function returns [SQLITE_READONLY]. +** +** {F17873} This function may only modify the contents of the blob; it is +** not possible to increase the size of a blob using this API. +** {F17874} If offset iOffset is less than n bytes from the end of the blob, +** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** +** {F17876} On success, SQLITE_OK is returned. Otherwise, an +** [error code] or an [extended error code] is returned. +*/ +int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects {F11200} +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** {F11201} The sqlite3_vfs_find() interface returns a pointer to +** a VFS given its name. {F11202} Names are case sensitive. +** {F11203} Names are zero-terminated UTF-8 strings. +** {F11204} If there is no match, a NULL +** pointer is returned. {F11205} If zVfsName is NULL then the default +** VFS is returned. {END} +** +** {F11210} New VFSes are registered with sqlite3_vfs_register(). +** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. +** {F11212} The same VFS can be registered multiple times without injury. +** {F11213} To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. {U11214} If two different VFSes with the +** same name are registered, the behavior is undefined. {U11215} If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. +** {F11221} If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary. +*/ +sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes {F17000} +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. The following +** implementations are available in the SQLite core: +** +**
    +**
  • SQLITE_MUTEX_OS2 +**
  • SQLITE_MUTEX_PTHREAD +**
  • SQLITE_MUTEX_W32 +**
  • SQLITE_MUTEX_NOOP +**
+** +** The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. The SQLITE_MUTEX_OS2, +** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations +** are appropriate for use on os/2, unix, and windows. +** +** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. The +** mutex interface routines defined here become external +** references in the SQLite library for which implementations +** must be provided by the application. This facility allows an +** application that links against SQLite to provide its own mutex +** implementation without having to modify the SQLite core. +** +** {F17011} The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. {F17012} If it returns NULL +** that means that a mutex could not be allocated. {F17013} SQLite +** will unwind its stack and return an error. {F17014} The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_MEM2 +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
{END} +** +** {F17015} The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. {F17016} But SQLite will only request a recursive mutex in +** cases where it really needs one. {END} If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. {END} Four static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. {F17034} But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. {END} +** +** {F17019} The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every +** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in +** use when they are deallocated. {U17022} Attempting to deallocate a static +** mutex results in undefined behavior. {F17023} SQLite never deallocates +** a static mutex. {END} +** +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. {F17024} If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. {F17026} Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** {F17027} In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. {U17028} If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** {F17029} SQLite will never exhibit +** such behavior in its own use of mutexes. {END} +** +** Some systems (ex: windows95) do not the operation implemented by +** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will +** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} +** +** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. {U17032} The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. {F17033} SQLite will +** never do either. {END} +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int); +void sqlite3_mutex_free(sqlite3_mutex*); +void sqlite3_mutex_enter(sqlite3_mutex*); +int sqlite3_mutex_try(sqlite3_mutex*); +void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Verifcation Routines {F17080} +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. {F17081} The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. {F17082} The core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. {U17087} External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** {F17083} These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. {END} +** +** {X17084} The implementation is not required to provided versions of these +** routines that actually work. +** If the implementation does not provide working +** versions of these routines, it should at least provide stubs +** that always return true so that one does not get spurious +** assertion failures. {END} +** +** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. {END} This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But the +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +int sqlite3_mutex_held(sqlite3_mutex*); +int sqlite3_mutex_notheld(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Types {F17001} +** +** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. {END} +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MASTER 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ + +/* +** CAPI3REF: Low-Level Control Of Database Files {F11300} +** +** {F11301} The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. {F11302} The +** name of the database is the name assigned to the database by the +** ATTACH SQL command that opened the +** database. {F11303} To control the main database file, use the name "main" +** or a NULL pointer. {F11304} The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. {F11305} The return value of the xFileControl +** method becomes the return value of this routine. +** +** {F11306} If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. {F11307} This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might +** also return SQLITE_ERROR. {U11309} There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. {END} +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface {F11400} +** +** The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. The first parameter a operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes {F11410} +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meansing are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FAULT_CONFIG 1 +#define SQLITE_TESTCTRL_FAULT_FAILURES 2 +#define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES 3 +#define SQLITE_TESTCTRL_FAULT_PENDING 4 + + + + + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/README.txt b/client/src/thirdparty/sqlite-3.4.2/ext/README.txt new file mode 100644 index 0000000..009495f --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/README.txt @@ -0,0 +1,2 @@ +Version loadable extensions to SQLite are found in subfolders +of this folder. diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Entries b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Entries new file mode 100644 index 0000000..511e1a0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Entries @@ -0,0 +1,15 @@ +/README.txt/1.1/Tue Aug 22 14:45:37 2006// +/fts1.h/1.2/Wed Sep 13 18:40:26 2006// +/fts1_hash.c/1.1/Thu Aug 31 15:07:15 2006// +/fts1_hash.h/1.1/Thu Aug 31 15:07:15 2006// +/fts1_porter.c/1.6/Fri Nov 30 01:28:10 2007// +/fts1_tokenizer.h/1.4/Sun Oct 1 18:41:20 2006// +/fts1_tokenizer1.c/1.8/Fri Nov 30 01:28:10 2007// +/fts1.c/1.55/Thu Dec 13 21:45:43 2007// +/ft_hash.c/1.1/Wed Aug 23 23:58:50 2006// +/ft_hash.h/1.1/Wed Aug 23 23:58:50 2006// +/fulltext.c/1.3/Mon Aug 28 23:46:02 2006// +/fulltext.h/1.1/Wed Aug 23 23:58:50 2006// +/simple_tokenizer.c/1.3/Wed Aug 30 21:40:30 2006// +/tokenizer.h/1.1/Wed Aug 23 23:58:50 2006// +D diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Repository b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Repository new file mode 100644 index 0000000..18923d9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Repository @@ -0,0 +1 @@ +sqlite/ext/fts1 diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Root b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Root new file mode 100644 index 0000000..a3ae5d0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/CVS/Root @@ -0,0 +1 @@ +:pserver:drh@sqlite.org:/sqlite diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/README.txt b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/README.txt new file mode 100644 index 0000000..292b7da --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/README.txt @@ -0,0 +1,2 @@ +This folder contains source code to the first full-text search +extension for SQLite. diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.c new file mode 100644 index 0000000..8b3a706 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.c @@ -0,0 +1,404 @@ +/* +** 2001 September 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 is the implementation of generic hash-tables used in SQLite. +** We've modified it slightly to serve as a standalone hash table +** implementation for the full-text indexing module. +*/ +#include +#include +#include + +#include "ft_hash.h" + +void *malloc_and_zero(int n){ + void *p = malloc(n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +** keyClass is one of the constants HASH_INT, HASH_POINTER, +** HASH_BINARY, or HASH_STRING. The value of keyClass +** determines what kind of key the hash table will use. "copyKey" is +** true if the hash table should make its own private copy of keys and +** false if it should just use the supplied pointer. CopyKey only makes +** sense for HASH_STRING and HASH_BINARY and is ignored +** for other key classes. +*/ +void HashInit(Hash *pNew, int keyClass, int copyKey){ + assert( pNew!=0 ); + assert( keyClass>=HASH_STRING && keyClass<=HASH_BINARY ); + pNew->keyClass = keyClass; +#if 0 + if( keyClass==HASH_POINTER || keyClass==HASH_INT ) copyKey = 0; +#endif + pNew->copyKey = copyKey; + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; + pNew->xMalloc = malloc_and_zero; + pNew->xFree = free; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +void HashClear(Hash *pH){ + HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + if( pH->ht ) pH->xFree(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + HashElem *next_elem = elem->next; + if( pH->copyKey && elem->pKey ){ + pH->xFree(elem->pKey); + } + pH->xFree(elem); + elem = next_elem; + } + pH->count = 0; +} + +#if 0 /* NOT USED */ +/* +** Hash and comparison functions when the mode is HASH_INT +*/ +static int intHash(const void *pKey, int nKey){ + return nKey ^ (nKey<<8) ^ (nKey>>8); +} +static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + return n2 - n1; +} +#endif + +#if 0 /* NOT USED */ +/* +** Hash and comparison functions when the mode is HASH_POINTER +*/ +static int ptrHash(const void *pKey, int nKey){ + uptr x = Addr(pKey); + return x ^ (x<<8) ^ (x>>8); +} +static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( pKey1==pKey2 ) return 0; + if( pKey1 0 ){ + h = (h<<3) ^ h ^ *z++; + nKey--; + } + return h & 0x7fffffff; +} +static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return strncmp((const char*)pKey1,(const char*)pKey2,n1); +} + +/* +** Hash and comparison functions when the mode is HASH_BINARY +*/ +static int binHash(const void *pKey, int nKey){ + int h = 0; + const char *z = (const char *)pKey; + while( nKey-- > 0 ){ + h = (h<<3) ^ h ^ *(z++); + } + return h & 0x7fffffff; +} +static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return memcmp(pKey1,pKey2,n1); +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** The C syntax in this function definition may be unfamilar to some +** programmers, so we provide the following additional explanation: +** +** The name of the function is "hashFunction". The function takes a +** single parameter "keyClass". The return value of hashFunction() +** is a pointer to another function. Specifically, the return value +** of hashFunction() is a pointer to a function that takes two parameters +** with types "const void*" and "int" and returns an "int". +*/ +static int (*hashFunction(int keyClass))(const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ + switch( keyClass ){ + case HASH_INT: return &intHash; + case HASH_POINTER: return &ptrHash; + case HASH_STRING: return &strHash; + case HASH_BINARY: return &binHash;; + default: break; + } + return 0; +#else + if( keyClass==HASH_STRING ){ + return &strHash; + }else{ + assert( keyClass==HASH_BINARY ); + return &binHash; + } +#endif +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** For help in interpreted the obscure C code in the function definition, +** see the header comment on the previous function. +*/ +static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ + switch( keyClass ){ + case HASH_INT: return &intCompare; + case HASH_POINTER: return &ptrCompare; + case HASH_STRING: return &strCompare; + case HASH_BINARY: return &binCompare; + default: break; + } + return 0; +#else + if( keyClass==HASH_STRING ){ + return &strCompare; + }else{ + assert( keyClass==HASH_BINARY ); + return &binCompare; + } +#endif +} + +/* Link an element into the hash table +*/ +static void insertElement( + Hash *pH, /* The complete hash table */ + struct _ht *pEntry, /* The entry into which pNew is inserted */ + HashElem *pNew /* The element to be inserted */ +){ + HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** "new_size" must be a power of 2. The hash table might fail +** to resize if sqliteMalloc() fails. +*/ +static void rehash(Hash *pH, int new_size){ + struct _ht *new_ht; /* The new hash table */ + HashElem *elem, *next_elem; /* For looping over existing elements */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( (new_size & (new_size-1))==0 ); + new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) ); + if( new_ht==0 ) return; + if( pH->ht ) pH->xFree(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size; + xHash = hashFunction(pH->keyClass); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + next_elem = elem->next; + insertElement(pH, &new_ht[h], elem); + } +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. +*/ +static HashElem *findElementGivenHash( + const Hash *pH, /* The pH to be searched */ + const void *pKey, /* The key we are searching for */ + int nKey, + int h /* The hash for this key. */ +){ + HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + int (*xCompare)(const void*,int,const void*,int); /* comparison function */ + + if( pH->ht ){ + struct _ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + xCompare = compareFunction(pH->keyClass); + while( count-- && elem ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void removeElementGivenHash( + Hash *pH, /* The pH containing "elem" */ + HashElem* elem, /* The element to be removed from the pH */ + int h /* Hash value for the element */ +){ + struct _ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; + } + if( pH->copyKey && elem->pKey ){ + pH->xFree(elem->pKey); + } + pH->xFree( elem ); + pH->count--; + if( pH->count<=0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + HashClear(pH); + } +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +void *HashFind(const Hash *pH, const void *pKey, int nKey){ + int h; /* A hash on key */ + HashElem *elem; /* The element that matches key */ + int (*xHash)(const void*,int); /* The hash function */ + + if( pH==0 || pH->ht==0 ) return 0; + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + h = (*xHash)(pKey,nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1)); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey,nKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created. A copy of the key is made if the copyKey +** flag is set. NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +void *HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ + int hraw; /* Raw hash value of the key */ + int h; /* the hash of the key modulo hash table size */ + HashElem *elem; /* Used to loop thru the element list */ + HashElem *new_elem; /* New element added to the pH */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( pH!=0 ); + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + hraw = (*xHash)(pKey, nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + elem = findElementGivenHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + } + return old_data; + } + if( data==0 ) return 0; + new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) ); + if( new_elem==0 ) return data; + if( pH->copyKey && pKey!=0 ){ + new_elem->pKey = pH->xMalloc( nKey ); + if( new_elem->pKey==0 ){ + pH->xFree(new_elem); + return data; + } + memcpy((void*)new_elem->pKey, pKey, nKey); + }else{ + new_elem->pKey = (void*)pKey; + } + new_elem->nKey = nKey; + pH->count++; + if( pH->htsize==0 ){ + rehash(pH,8); + if( pH->htsize==0 ){ + pH->count = 0; + pH->xFree(new_elem); + return data; + } + } + if( pH->count > pH->htsize ){ + rehash(pH,pH->htsize*2); + } + assert( pH->htsize>0 ); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + insertElement(pH, &pH->ht[h], new_elem); + new_elem->data = data; + return 0; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.h new file mode 100644 index 0000000..93b6dcf --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/ft_hash.h @@ -0,0 +1,111 @@ +/* +** 2001 September 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 is the header file for the generic hash-table implemenation +** used in SQLite. We've modified it slightly to serve as a standalone +** hash table implementation for the full-text indexing module. +** +*/ +#ifndef _HASH_H_ +#define _HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct Hash { + char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ + char copyKey; /* True if copy of key made on insert */ + int count; /* Number of entries in this table */ + HashElem *first; /* The first element of the array */ + void *(*xMalloc)(int); /* malloc() function to use */ + void (*xFree)(void *); /* free() function to use */ + int htsize; /* Number of buckets in the hash table */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** There are 4 different modes of operation for a hash table: +** +** HASH_INT nKey is used as the key and pKey is ignored. +** +** HASH_POINTER pKey is used as the key and nKey is ignored. +** +** HASH_STRING pKey points to a string that is nKey bytes long +** (including the null-terminator, if any). Case +** is respected in comparisons. +** +** HASH_BINARY pKey points to binary data nKey bytes long. +** memcmp() is used to compare keys. +** +** A copy of the key is made for HASH_STRING and HASH_BINARY +** if the copyKey parameter to HashInit is 1. +*/ +/* #define HASH_INT 1 // NOT USED */ +/* #define HASH_POINTER 2 // NOT USED */ +#define HASH_STRING 3 +#define HASH_BINARY 4 + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +void HashInit(Hash*, int keytype, int copyKey); +void *HashInsert(Hash*, const void *pKey, int nKey, void *pData); +void *HashFind(const Hash*, const void *pKey, int nKey); +void HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=HashFirst(&h); p; p=HashNext(p)){ +** SomeStructure *pData = HashData(p); +** // do something with pData +** } +*/ +#define HashFirst(H) ((H)->first) +#define HashNext(E) ((E)->next) +#define HashData(E) ((E)->data) +#define HashKey(E) ((E)->pKey) +#define HashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define HashCount(H) ((H)->count) + +#endif /* _HASH_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.c new file mode 100644 index 0000000..f2650e2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.c @@ -0,0 +1,3345 @@ +/* fts1 has a design flaw which can lead to database corruption (see +** below). It is recommended not to use it any longer, instead use +** fts3 (or higher). If you believe that your use of fts1 is safe, +** add -DSQLITE_ENABLE_BROKEN_FTS1=1 to your CFLAGS. +*/ +#if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1)) \ + && !defined(SQLITE_ENABLE_BROKEN_FTS1) +#error fts1 has a design flaw and has been deprecated. +#endif +/* The flaw is that fts1 uses the content table's unaliased rowid as +** the unique docid. fts1 embeds the rowid in the index it builds, +** and expects the rowid to not change. The SQLite VACUUM operation +** will renumber such rowids, thereby breaking fts1. If you are using +** fts1 in a system which has disabled VACUUM, then you can continue +** to use it safely. Note that PRAGMA auto_vacuum does NOT disable +** VACUUM, though systems using auto_vacuum are unlikely to invoke +** VACUUM. +** +** fts1 should be safe even across VACUUM if you only insert documents +** and never delete. +*/ + +/* The author disclaims copyright to this source code. + * + * This is an SQLite module implementing full-text search. + */ + +/* +** The code in this file is only compiled if: +** +** * The FTS1 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS1 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS1 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) + +#if defined(SQLITE_ENABLE_FTS1) && !defined(SQLITE_CORE) +# define SQLITE_CORE 1 +#endif + +#include +#include +#include +#include +#include + +#include "fts1.h" +#include "fts1_hash.h" +#include "fts1_tokenizer.h" +#include "sqlite3.h" +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + + +#if 0 +# define TRACE(A) printf A; fflush(stdout) +#else +# define TRACE(A) +#endif + +/* utility functions */ + +typedef struct StringBuffer { + int len; /* length, not including null terminator */ + int alloced; /* Space allocated for s[] */ + char *s; /* Content of the string */ +} StringBuffer; + +static void initStringBuffer(StringBuffer *sb){ + sb->len = 0; + sb->alloced = 100; + sb->s = malloc(100); + sb->s[0] = '\0'; +} + +static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){ + if( sb->len + nFrom >= sb->alloced ){ + sb->alloced = sb->len + nFrom + 100; + sb->s = realloc(sb->s, sb->alloced+1); + if( sb->s==0 ){ + initStringBuffer(sb); + return; + } + } + memcpy(sb->s + sb->len, zFrom, nFrom); + sb->len += nFrom; + sb->s[sb->len] = 0; +} +static void append(StringBuffer *sb, const char *zFrom){ + nappend(sb, zFrom, strlen(zFrom)); +} + +/* We encode variable-length integers in little-endian order using seven bits + * per byte as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** and so on. +*/ + +/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */ +#define VARINT_MAX 10 + +/* Write a 64-bit variable-length integer to memory starting at p[0]. + * The length of data written will be between 1 and VARINT_MAX bytes. + * The number of bytes written is returned. */ +static int putVarint(char *p, sqlite_int64 v){ + unsigned char *q = (unsigned char *) p; + sqlite_uint64 vu = v; + do{ + *q++ = (unsigned char) ((vu & 0x7f) | 0x80); + vu >>= 7; + }while( vu!=0 ); + q[-1] &= 0x7f; /* turn off high bit in final byte */ + assert( q - (unsigned char *)p <= VARINT_MAX ); + return (int) (q - (unsigned char *)p); +} + +/* Read a 64-bit variable-length integer from memory starting at p[0]. + * Return the number of bytes read, or 0 on error. + * The value is stored in *v. */ +static int getVarint(const char *p, sqlite_int64 *v){ + const unsigned char *q = (const unsigned char *) p; + sqlite_uint64 x = 0, y = 1; + while( (*q & 0x80) == 0x80 ){ + x += y * (*q++ & 0x7f); + y <<= 7; + if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */ + assert( 0 ); + return 0; + } + } + x += y * (*q++); + *v = (sqlite_int64) x; + return (int) (q - (unsigned char *)p); +} + +static int getVarint32(const char *p, int *pi){ + sqlite_int64 i; + int ret = getVarint(p, &i); + *pi = (int) i; + assert( *pi==i ); + return ret; +} + +/*** Document lists *** + * + * A document list holds a sorted list of varint-encoded document IDs. + * + * A doclist with type DL_POSITIONS_OFFSETS is stored like this: + * + * array { + * varint docid; + * array { + * varint position; (delta from previous position plus POS_BASE) + * varint startOffset; (delta from previous startOffset) + * varint endOffset; (delta from startOffset) + * } + * } + * + * Here, array { X } means zero or more occurrences of X, adjacent in memory. + * + * A position list may hold positions for text in multiple columns. A position + * POS_COLUMN is followed by a varint containing the index of the column for + * following positions in the list. Any positions appearing before any + * occurrences of POS_COLUMN are for column 0. + * + * A doclist with type DL_POSITIONS is like the above, but holds only docids + * and positions without offset information. + * + * A doclist with type DL_DOCIDS is like the above, but holds only docids + * without positions or offset information. + * + * On disk, every document list has positions and offsets, so we don't bother + * to serialize a doclist's type. + * + * We don't yet delta-encode document IDs; doing so will probably be a + * modest win. + * + * NOTE(shess) I've thought of a slightly (1%) better offset encoding. + * After the first offset, estimate the next offset by using the + * current token position and the previous token position and offset, + * offset to handle some variance. So the estimate would be + * (iPosition*w->iStartOffset/w->iPosition-64), which is delta-encoded + * as normal. Offsets more than 64 chars from the estimate are + * encoded as the delta to the previous start offset + 128. An + * additional tiny increment can be gained by using the end offset of + * the previous token to make the estimate a tiny bit more precise. +*/ + +/* It is not safe to call isspace(), tolower(), or isalnum() on +** hi-bit-set characters. This is the same solution used in the +** tokenizer. +*/ +/* TODO(shess) The snippet-generation code should be using the +** tokenizer-generated tokens rather than doing its own local +** tokenization. +*/ +/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ +static int safe_isspace(char c){ + return (c&0x80)==0 ? isspace(c) : 0; +} +static int safe_tolower(char c){ + return (c&0x80)==0 ? tolower(c) : c; +} +static int safe_isalnum(char c){ + return (c&0x80)==0 ? isalnum(c) : 0; +} + +typedef enum DocListType { + DL_DOCIDS, /* docids only */ + DL_POSITIONS, /* docids + positions */ + DL_POSITIONS_OFFSETS /* docids + positions + offsets */ +} DocListType; + +/* +** By default, only positions and not offsets are stored in the doclists. +** To change this so that offsets are stored too, compile with +** +** -DDL_DEFAULT=DL_POSITIONS_OFFSETS +** +*/ +#ifndef DL_DEFAULT +# define DL_DEFAULT DL_POSITIONS +#endif + +typedef struct DocList { + char *pData; + int nData; + DocListType iType; + int iLastColumn; /* the last column written */ + int iLastPos; /* the last position written */ + int iLastOffset; /* the last start offset written */ +} DocList; + +enum { + POS_END = 0, /* end of this position list */ + POS_COLUMN, /* followed by new column number */ + POS_BASE +}; + +/* Initialize a new DocList to hold the given data. */ +static void docListInit(DocList *d, DocListType iType, + const char *pData, int nData){ + d->nData = nData; + if( nData>0 ){ + d->pData = malloc(nData); + memcpy(d->pData, pData, nData); + } else { + d->pData = NULL; + } + d->iType = iType; + d->iLastColumn = 0; + d->iLastPos = d->iLastOffset = 0; +} + +/* Create a new dynamically-allocated DocList. */ +static DocList *docListNew(DocListType iType){ + DocList *d = (DocList *) malloc(sizeof(DocList)); + docListInit(d, iType, 0, 0); + return d; +} + +static void docListDestroy(DocList *d){ + free(d->pData); +#ifndef NDEBUG + memset(d, 0x55, sizeof(*d)); +#endif +} + +static void docListDelete(DocList *d){ + docListDestroy(d); + free(d); +} + +static char *docListEnd(DocList *d){ + return d->pData + d->nData; +} + +/* Append a varint to a DocList's data. */ +static void appendVarint(DocList *d, sqlite_int64 i){ + char c[VARINT_MAX]; + int n = putVarint(c, i); + d->pData = realloc(d->pData, d->nData + n); + memcpy(d->pData + d->nData, c, n); + d->nData += n; +} + +static void docListAddDocid(DocList *d, sqlite_int64 iDocid){ + appendVarint(d, iDocid); + if( d->iType>=DL_POSITIONS ){ + appendVarint(d, POS_END); /* initially empty position list */ + d->iLastColumn = 0; + d->iLastPos = d->iLastOffset = 0; + } +} + +/* helper function for docListAddPos and docListAddPosOffset */ +static void addPos(DocList *d, int iColumn, int iPos){ + assert( d->nData>0 ); + --d->nData; /* remove previous terminator */ + if( iColumn!=d->iLastColumn ){ + assert( iColumn>d->iLastColumn ); + appendVarint(d, POS_COLUMN); + appendVarint(d, iColumn); + d->iLastColumn = iColumn; + d->iLastPos = d->iLastOffset = 0; + } + assert( iPos>=d->iLastPos ); + appendVarint(d, iPos-d->iLastPos+POS_BASE); + d->iLastPos = iPos; +} + +/* Add a position to the last position list in a doclist. */ +static void docListAddPos(DocList *d, int iColumn, int iPos){ + assert( d->iType==DL_POSITIONS ); + addPos(d, iColumn, iPos); + appendVarint(d, POS_END); /* add new terminator */ +} + +/* +** Add a position and starting and ending offsets to a doclist. +** +** If the doclist is setup to handle only positions, then insert +** the position only and ignore the offsets. +*/ +static void docListAddPosOffset( + DocList *d, /* Doclist under construction */ + int iColumn, /* Column the inserted term is part of */ + int iPos, /* Position of the inserted term */ + int iStartOffset, /* Starting offset of inserted term */ + int iEndOffset /* Ending offset of inserted term */ +){ + assert( d->iType>=DL_POSITIONS ); + addPos(d, iColumn, iPos); + if( d->iType==DL_POSITIONS_OFFSETS ){ + assert( iStartOffset>=d->iLastOffset ); + appendVarint(d, iStartOffset-d->iLastOffset); + d->iLastOffset = iStartOffset; + assert( iEndOffset>=iStartOffset ); + appendVarint(d, iEndOffset-iStartOffset); + } + appendVarint(d, POS_END); /* add new terminator */ +} + +/* +** A DocListReader object is a cursor into a doclist. Initialize +** the cursor to the beginning of the doclist by calling readerInit(). +** Then use routines +** +** peekDocid() +** readDocid() +** readPosition() +** skipPositionList() +** and so forth... +** +** to read information out of the doclist. When we reach the end +** of the doclist, atEnd() returns TRUE. +*/ +typedef struct DocListReader { + DocList *pDoclist; /* The document list we are stepping through */ + char *p; /* Pointer to next unread byte in the doclist */ + int iLastColumn; + int iLastPos; /* the last position read, or -1 when not in a position list */ +} DocListReader; + +/* +** Initialize the DocListReader r to point to the beginning of pDoclist. +*/ +static void readerInit(DocListReader *r, DocList *pDoclist){ + r->pDoclist = pDoclist; + if( pDoclist!=NULL ){ + r->p = pDoclist->pData; + } + r->iLastColumn = -1; + r->iLastPos = -1; +} + +/* +** Return TRUE if we have reached then end of pReader and there is +** nothing else left to read. +*/ +static int atEnd(DocListReader *pReader){ + return pReader->pDoclist==0 || (pReader->p >= docListEnd(pReader->pDoclist)); +} + +/* Peek at the next docid without advancing the read pointer. +*/ +static sqlite_int64 peekDocid(DocListReader *pReader){ + sqlite_int64 ret; + assert( !atEnd(pReader) ); + assert( pReader->iLastPos==-1 ); + getVarint(pReader->p, &ret); + return ret; +} + +/* Read the next docid. See also nextDocid(). +*/ +static sqlite_int64 readDocid(DocListReader *pReader){ + sqlite_int64 ret; + assert( !atEnd(pReader) ); + assert( pReader->iLastPos==-1 ); + pReader->p += getVarint(pReader->p, &ret); + if( pReader->pDoclist->iType>=DL_POSITIONS ){ + pReader->iLastColumn = 0; + pReader->iLastPos = 0; + } + return ret; +} + +/* Read the next position and column index from a position list. + * Returns the position, or -1 at the end of the list. */ +static int readPosition(DocListReader *pReader, int *iColumn){ + int i; + int iType = pReader->pDoclist->iType; + + if( pReader->iLastPos==-1 ){ + return -1; + } + assert( !atEnd(pReader) ); + + if( iTypep += getVarint32(pReader->p, &i); + if( i==POS_END ){ + pReader->iLastColumn = pReader->iLastPos = -1; + *iColumn = -1; + return -1; + } + if( i==POS_COLUMN ){ + pReader->p += getVarint32(pReader->p, &pReader->iLastColumn); + pReader->iLastPos = 0; + pReader->p += getVarint32(pReader->p, &i); + assert( i>=POS_BASE ); + } + pReader->iLastPos += ((int) i)-POS_BASE; + if( iType>=DL_POSITIONS_OFFSETS ){ + /* Skip over offsets, ignoring them for now. */ + int iStart, iEnd; + pReader->p += getVarint32(pReader->p, &iStart); + pReader->p += getVarint32(pReader->p, &iEnd); + } + *iColumn = pReader->iLastColumn; + return pReader->iLastPos; +} + +/* Skip past the end of a position list. */ +static void skipPositionList(DocListReader *pReader){ + DocList *p = pReader->pDoclist; + if( p && p->iType>=DL_POSITIONS ){ + int iColumn; + while( readPosition(pReader, &iColumn)!=-1 ){} + } +} + +/* Skip over a docid, including its position list if the doclist has + * positions. */ +static void skipDocument(DocListReader *pReader){ + readDocid(pReader); + skipPositionList(pReader); +} + +/* Skip past all docids which are less than [iDocid]. Returns 1 if a docid + * matching [iDocid] was found. */ +static int skipToDocid(DocListReader *pReader, sqlite_int64 iDocid){ + sqlite_int64 d = 0; + while( !atEnd(pReader) && (d=peekDocid(pReader))iType>=DL_POSITIONS ){ + int iPos, iCol; + const char *zDiv = ""; + printf("("); + while( (iPos = readPosition(&r, &iCol))>=0 ){ + printf("%s%d:%d", zDiv, iCol, iPos); + zDiv = ":"; + } + printf(")"); + } + } + printf("\n"); + fflush(stdout); +} +#endif /* SQLITE_DEBUG */ + +/* Trim the given doclist to contain only positions in column + * [iRestrictColumn]. */ +static void docListRestrictColumn(DocList *in, int iRestrictColumn){ + DocListReader r; + DocList out; + + assert( in->iType>=DL_POSITIONS ); + readerInit(&r, in); + docListInit(&out, DL_POSITIONS, NULL, 0); + + while( !atEnd(&r) ){ + sqlite_int64 iDocid = readDocid(&r); + int iPos, iColumn; + + docListAddDocid(&out, iDocid); + while( (iPos = readPosition(&r, &iColumn)) != -1 ){ + if( iColumn==iRestrictColumn ){ + docListAddPos(&out, iColumn, iPos); + } + } + } + + docListDestroy(in); + *in = out; +} + +/* Trim the given doclist by discarding any docids without any remaining + * positions. */ +static void docListDiscardEmpty(DocList *in) { + DocListReader r; + DocList out; + + /* TODO: It would be nice to implement this operation in place; that + * could save a significant amount of memory in queries with long doclists. */ + assert( in->iType>=DL_POSITIONS ); + readerInit(&r, in); + docListInit(&out, DL_POSITIONS, NULL, 0); + + while( !atEnd(&r) ){ + sqlite_int64 iDocid = readDocid(&r); + int match = 0; + int iPos, iColumn; + while( (iPos = readPosition(&r, &iColumn)) != -1 ){ + if( !match ){ + docListAddDocid(&out, iDocid); + match = 1; + } + docListAddPos(&out, iColumn, iPos); + } + } + + docListDestroy(in); + *in = out; +} + +/* Helper function for docListUpdate() and docListAccumulate(). +** Splices a doclist element into the doclist represented by r, +** leaving r pointing after the newly spliced element. +*/ +static void docListSpliceElement(DocListReader *r, sqlite_int64 iDocid, + const char *pSource, int nSource){ + DocList *d = r->pDoclist; + char *pTarget; + int nTarget, found; + + found = skipToDocid(r, iDocid); + + /* Describe slice in d to place pSource/nSource. */ + pTarget = r->p; + if( found ){ + skipDocument(r); + nTarget = r->p-pTarget; + }else{ + nTarget = 0; + } + + /* The sense of the following is that there are three possibilities. + ** If nTarget==nSource, we should not move any memory nor realloc. + ** If nTarget>nSource, trim target and realloc. + ** If nTargetnSource ){ + memmove(pTarget+nSource, pTarget+nTarget, docListEnd(d)-(pTarget+nTarget)); + } + if( nTarget!=nSource ){ + int iDoclist = pTarget-d->pData; + d->pData = realloc(d->pData, d->nData+nSource-nTarget); + pTarget = d->pData+iDoclist; + } + if( nTargetnData += nSource-nTarget; + r->p = pTarget+nSource; +} + +/* Insert/update pUpdate into the doclist. */ +static void docListUpdate(DocList *d, DocList *pUpdate){ + DocListReader reader; + + assert( d!=NULL && pUpdate!=NULL ); + assert( d->iType==pUpdate->iType); + + readerInit(&reader, d); + docListSpliceElement(&reader, firstDocid(pUpdate), + pUpdate->pData, pUpdate->nData); +} + +/* Propagate elements from pUpdate to pAcc, overwriting elements with +** matching docids. +*/ +static void docListAccumulate(DocList *pAcc, DocList *pUpdate){ + DocListReader accReader, updateReader; + + /* Handle edge cases where one doclist is empty. */ + assert( pAcc!=NULL ); + if( pUpdate==NULL || pUpdate->nData==0 ) return; + if( pAcc->nData==0 ){ + pAcc->pData = malloc(pUpdate->nData); + memcpy(pAcc->pData, pUpdate->pData, pUpdate->nData); + pAcc->nData = pUpdate->nData; + return; + } + + readerInit(&accReader, pAcc); + readerInit(&updateReader, pUpdate); + + while( !atEnd(&updateReader) ){ + char *pSource = updateReader.p; + sqlite_int64 iDocid = readDocid(&updateReader); + skipPositionList(&updateReader); + docListSpliceElement(&accReader, iDocid, pSource, updateReader.p-pSource); + } +} + +/* +** Read the next docid off of pIn. Return 0 if we reach the end. +* +* TODO: This assumes that docids are never 0, but they may actually be 0 since +* users can choose docids when inserting into a full-text table. Fix this. +*/ +static sqlite_int64 nextDocid(DocListReader *pIn){ + skipPositionList(pIn); + return atEnd(pIn) ? 0 : readDocid(pIn); +} + +/* +** pLeft and pRight are two DocListReaders that are pointing to +** positions lists of the same document: iDocid. +** +** If there are no instances in pLeft or pRight where the position +** of pLeft is one less than the position of pRight, then this +** routine adds nothing to pOut. +** +** If there are one or more instances where positions from pLeft +** are exactly one less than positions from pRight, then add a new +** document record to pOut. If pOut wants to hold positions, then +** include the positions from pRight that are one more than a +** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1. +** +** pLeft and pRight are left pointing at the next document record. +*/ +static void mergePosList( + DocListReader *pLeft, /* Left position list */ + DocListReader *pRight, /* Right position list */ + sqlite_int64 iDocid, /* The docid from pLeft and pRight */ + DocList *pOut /* Write the merged document record here */ +){ + int iLeftCol, iLeftPos = readPosition(pLeft, &iLeftCol); + int iRightCol, iRightPos = readPosition(pRight, &iRightCol); + int match = 0; + + /* Loop until we've reached the end of both position lists. */ + while( iLeftPos!=-1 && iRightPos!=-1 ){ + if( iLeftCol==iRightCol && iLeftPos+1==iRightPos ){ + if( !match ){ + docListAddDocid(pOut, iDocid); + match = 1; + } + if( pOut->iType>=DL_POSITIONS ){ + docListAddPos(pOut, iRightCol, iRightPos); + } + iLeftPos = readPosition(pLeft, &iLeftCol); + iRightPos = readPosition(pRight, &iRightCol); + }else if( iRightCol=0 ) skipPositionList(pLeft); + if( iRightPos>=0 ) skipPositionList(pRight); +} + +/* We have two doclists: pLeft and pRight. +** Write the phrase intersection of these two doclists into pOut. +** +** A phrase intersection means that two documents only match +** if pLeft.iPos+1==pRight.iPos. +** +** The output pOut may or may not contain positions. If pOut +** does contain positions, they are the positions of pRight. +*/ +static void docListPhraseMerge( + DocList *pLeft, /* Doclist resulting from the words on the left */ + DocList *pRight, /* Doclist for the next word to the right */ + DocList *pOut /* Write the combined doclist here */ +){ + DocListReader left, right; + sqlite_int64 docidLeft, docidRight; + + readerInit(&left, pLeft); + readerInit(&right, pRight); + docidLeft = nextDocid(&left); + docidRight = nextDocid(&right); + + while( docidLeft>0 && docidRight>0 ){ + if( docidLeftiType0 && docidRight>0 ){ + if( docidLeft0 && docidRight>0 ){ + if( docidLeft<=docidRight ){ + docListAddDocid(pOut, docidLeft); + }else{ + docListAddDocid(pOut, docidRight); + } + priorLeft = docidLeft; + if( docidLeft<=docidRight ){ + docidLeft = nextDocid(&left); + } + if( docidRight>0 && docidRight<=priorLeft ){ + docidRight = nextDocid(&right); + } + } + while( docidLeft>0 ){ + docListAddDocid(pOut, docidLeft); + docidLeft = nextDocid(&left); + } + while( docidRight>0 ){ + docListAddDocid(pOut, docidRight); + docidRight = nextDocid(&right); + } +} + +/* We have two doclists: pLeft and pRight. +** Write into pOut all documents that occur in pLeft but not +** in pRight. +** +** Only docids are matched. Position information is ignored. +** +** The output pOut never holds positions. +*/ +static void docListExceptMerge( + DocList *pLeft, /* Doclist resulting from the words on the left */ + DocList *pRight, /* Doclist for the next word to the right */ + DocList *pOut /* Write the combined doclist here */ +){ + DocListReader left, right; + sqlite_int64 docidLeft, docidRight, priorLeft; + + readerInit(&left, pLeft); + readerInit(&right, pRight); + docidLeft = nextDocid(&left); + docidRight = nextDocid(&right); + + while( docidLeft>0 && docidRight>0 ){ + priorLeft = docidLeft; + if( docidLeft0 && docidRight<=priorLeft ){ + docidRight = nextDocid(&right); + } + } + while( docidLeft>0 ){ + docListAddDocid(pOut, docidLeft); + docidLeft = nextDocid(&left); + } +} + +static char *string_dup_n(const char *s, int n){ + char *str = malloc(n + 1); + memcpy(str, s, n); + str[n] = '\0'; + return str; +} + +/* Duplicate a string; the caller must free() the returned string. + * (We don't use strdup() since it is not part of the standard C library and + * may not be available everywhere.) */ +static char *string_dup(const char *s){ + return string_dup_n(s, strlen(s)); +} + +/* Format a string, replacing each occurrence of the % character with + * zDb.zName. This may be more convenient than sqlite_mprintf() + * when one string is used repeatedly in a format string. + * The caller must free() the returned string. */ +static char *string_format(const char *zFormat, + const char *zDb, const char *zName){ + const char *p; + size_t len = 0; + size_t nDb = strlen(zDb); + size_t nName = strlen(zName); + size_t nFullTableName = nDb+1+nName; + char *result; + char *r; + + /* first compute length needed */ + for(p = zFormat ; *p ; ++p){ + len += (*p=='%' ? nFullTableName : 1); + } + len += 1; /* for null terminator */ + + r = result = malloc(len); + for(p = zFormat; *p; ++p){ + if( *p=='%' ){ + memcpy(r, zDb, nDb); + r += nDb; + *r++ = '.'; + memcpy(r, zName, nName); + r += nName; + } else { + *r++ = *p; + } + } + *r++ = '\0'; + assert( r == result + len ); + return result; +} + +static int sql_exec(sqlite3 *db, const char *zDb, const char *zName, + const char *zFormat){ + char *zCommand = string_format(zFormat, zDb, zName); + int rc; + TRACE(("FTS1 sql: %s\n", zCommand)); + rc = sqlite3_exec(db, zCommand, NULL, 0, NULL); + free(zCommand); + return rc; +} + +static int sql_prepare(sqlite3 *db, const char *zDb, const char *zName, + sqlite3_stmt **ppStmt, const char *zFormat){ + char *zCommand = string_format(zFormat, zDb, zName); + int rc; + TRACE(("FTS1 prepare: %s\n", zCommand)); + rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL); + free(zCommand); + return rc; +} + +/* end utility functions */ + +/* Forward reference */ +typedef struct fulltext_vtab fulltext_vtab; + +/* A single term in a query is represented by an instances of +** the following structure. +*/ +typedef struct QueryTerm { + short int nPhrase; /* How many following terms are part of the same phrase */ + short int iPhrase; /* This is the i-th term of a phrase. */ + short int iColumn; /* Column of the index that must match this term */ + signed char isOr; /* this term is preceded by "OR" */ + signed char isNot; /* this term is preceded by "-" */ + char *pTerm; /* text of the term. '\000' terminated. malloced */ + int nTerm; /* Number of bytes in pTerm[] */ +} QueryTerm; + + +/* A query string is parsed into a Query structure. + * + * We could, in theory, allow query strings to be complicated + * nested expressions with precedence determined by parentheses. + * But none of the major search engines do this. (Perhaps the + * feeling is that an parenthesized expression is two complex of + * an idea for the average user to grasp.) Taking our lead from + * the major search engines, we will allow queries to be a list + * of terms (with an implied AND operator) or phrases in double-quotes, + * with a single optional "-" before each non-phrase term to designate + * negation and an optional OR connector. + * + * OR binds more tightly than the implied AND, which is what the + * major search engines seem to do. So, for example: + * + * [one two OR three] ==> one AND (two OR three) + * [one OR two three] ==> (one OR two) AND three + * + * A "-" before a term matches all entries that lack that term. + * The "-" must occur immediately before the term with in intervening + * space. This is how the search engines do it. + * + * A NOT term cannot be the right-hand operand of an OR. If this + * occurs in the query string, the NOT is ignored: + * + * [one OR -two] ==> one OR two + * + */ +typedef struct Query { + fulltext_vtab *pFts; /* The full text index */ + int nTerms; /* Number of terms in the query */ + QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */ + int nextIsOr; /* Set the isOr flag on the next inserted term */ + int nextColumn; /* Next word parsed must be in this column */ + int dfltColumn; /* The default column */ +} Query; + + +/* +** An instance of the following structure keeps track of generated +** matching-word offset information and snippets. +*/ +typedef struct Snippet { + int nMatch; /* Total number of matches */ + int nAlloc; /* Space allocated for aMatch[] */ + struct snippetMatch { /* One entry for each matching term */ + char snStatus; /* Status flag for use while constructing snippets */ + short int iCol; /* The column that contains the match */ + short int iTerm; /* The index in Query.pTerms[] of the matching term */ + short int nByte; /* Number of bytes in the term */ + int iStart; /* The offset to the first character of the term */ + } *aMatch; /* Points to space obtained from malloc */ + char *zOffset; /* Text rendering of aMatch[] */ + int nOffset; /* strlen(zOffset) */ + char *zSnippet; /* Snippet text */ + int nSnippet; /* strlen(zSnippet) */ +} Snippet; + + +typedef enum QueryType { + QUERY_GENERIC, /* table scan */ + QUERY_ROWID, /* lookup by rowid */ + QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/ +} QueryType; + +/* TODO(shess) CHUNK_MAX controls how much data we allow in segment 0 +** before we start aggregating into larger segments. Lower CHUNK_MAX +** means that for a given input we have more individual segments per +** term, which means more rows in the table and a bigger index (due to +** both more rows and bigger rowids). But it also reduces the average +** cost of adding new elements to the segment 0 doclist, and it seems +** to reduce the number of pages read and written during inserts. 256 +** was chosen by measuring insertion times for a certain input (first +** 10k documents of Enron corpus), though including query performance +** in the decision may argue for a larger value. +*/ +#define CHUNK_MAX 256 + +typedef enum fulltext_statement { + CONTENT_INSERT_STMT, + CONTENT_SELECT_STMT, + CONTENT_UPDATE_STMT, + CONTENT_DELETE_STMT, + + TERM_SELECT_STMT, + TERM_SELECT_ALL_STMT, + TERM_INSERT_STMT, + TERM_UPDATE_STMT, + TERM_DELETE_STMT, + + MAX_STMT /* Always at end! */ +} fulltext_statement; + +/* These must exactly match the enum above. */ +/* TODO(adam): Is there some risk that a statement (in particular, +** pTermSelectStmt) will be used in two cursors at once, e.g. if a +** query joins a virtual table to itself? If so perhaps we should +** move some of these to the cursor object. +*/ +static const char *const fulltext_zStatement[MAX_STMT] = { + /* CONTENT_INSERT */ NULL, /* generated in contentInsertStatement() */ + /* CONTENT_SELECT */ "select * from %_content where rowid = ?", + /* CONTENT_UPDATE */ NULL, /* generated in contentUpdateStatement() */ + /* CONTENT_DELETE */ "delete from %_content where rowid = ?", + + /* TERM_SELECT */ + "select rowid, doclist from %_term where term = ? and segment = ?", + /* TERM_SELECT_ALL */ + "select doclist from %_term where term = ? order by segment", + /* TERM_INSERT */ + "insert into %_term (rowid, term, segment, doclist) values (?, ?, ?, ?)", + /* TERM_UPDATE */ "update %_term set doclist = ? where rowid = ?", + /* TERM_DELETE */ "delete from %_term where rowid = ?", +}; + +/* +** A connection to a fulltext index is an instance of the following +** structure. The xCreate and xConnect methods create an instance +** of this structure and xDestroy and xDisconnect free that instance. +** All other methods receive a pointer to the structure as one of their +** arguments. +*/ +struct fulltext_vtab { + sqlite3_vtab base; /* Base class used by SQLite core */ + sqlite3 *db; /* The database connection */ + const char *zDb; /* logical database name */ + const char *zName; /* virtual table name */ + int nColumn; /* number of columns in virtual table */ + char **azColumn; /* column names. malloced */ + char **azContentColumn; /* column names in content table; malloced */ + sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ + + /* Precompiled statements which we keep as long as the table is + ** open. + */ + sqlite3_stmt *pFulltextStatements[MAX_STMT]; +}; + +/* +** When the core wants to do a query, it create a cursor using a +** call to xOpen. This structure is an instance of a cursor. It +** is destroyed by xClose. +*/ +typedef struct fulltext_cursor { + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ + QueryType iCursorType; /* Copy of sqlite3_index_info.idxNum */ + sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ + int eof; /* True if at End Of Results */ + Query q; /* Parsed query string */ + Snippet snippet; /* Cached snippet for the current row */ + int iColumn; /* Column being searched */ + DocListReader result; /* used when iCursorType == QUERY_FULLTEXT */ +} fulltext_cursor; + +static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){ + return (fulltext_vtab *) c->base.pVtab; +} + +static const sqlite3_module fulltextModule; /* forward declaration */ + +/* Append a list of strings separated by commas to a StringBuffer. */ +static void appendList(StringBuffer *sb, int nString, char **azString){ + int i; + for(i=0; i0 ) append(sb, ", "); + append(sb, azString[i]); + } +} + +/* Return a dynamically generated statement of the form + * insert into %_content (rowid, ...) values (?, ...) + */ +static const char *contentInsertStatement(fulltext_vtab *v){ + StringBuffer sb; + int i; + + initStringBuffer(&sb); + append(&sb, "insert into %_content (rowid, "); + appendList(&sb, v->nColumn, v->azContentColumn); + append(&sb, ") values (?"); + for(i=0; inColumn; ++i) + append(&sb, ", ?"); + append(&sb, ")"); + return sb.s; +} + +/* Return a dynamically generated statement of the form + * update %_content set [col_0] = ?, [col_1] = ?, ... + * where rowid = ? + */ +static const char *contentUpdateStatement(fulltext_vtab *v){ + StringBuffer sb; + int i; + + initStringBuffer(&sb); + append(&sb, "update %_content set "); + for(i=0; inColumn; ++i) { + if( i>0 ){ + append(&sb, ", "); + } + append(&sb, v->azContentColumn[i]); + append(&sb, " = ?"); + } + append(&sb, " where rowid = ?"); + return sb.s; +} + +/* Puts a freshly-prepared statement determined by iStmt in *ppStmt. +** If the indicated statement has never been prepared, it is prepared +** and cached, otherwise the cached version is reset. +*/ +static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + assert( iStmtpFulltextStatements[iStmt]==NULL ){ + const char *zStmt; + int rc; + switch( iStmt ){ + case CONTENT_INSERT_STMT: + zStmt = contentInsertStatement(v); break; + case CONTENT_UPDATE_STMT: + zStmt = contentUpdateStatement(v); break; + default: + zStmt = fulltext_zStatement[iStmt]; + } + rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt], + zStmt); + if( zStmt != fulltext_zStatement[iStmt]) free((void *) zStmt); + if( rc!=SQLITE_OK ) return rc; + } else { + int rc = sqlite3_reset(v->pFulltextStatements[iStmt]); + if( rc!=SQLITE_OK ) return rc; + } + + *ppStmt = v->pFulltextStatements[iStmt]; + return SQLITE_OK; +} + +/* Step the indicated statement, handling errors SQLITE_BUSY (by +** retrying) and SQLITE_SCHEMA (by re-preparing and transferring +** bindings to the new statement). +** TODO(adam): We should extend this function so that it can work with +** statements declared locally, not only globally cached statements. +*/ +static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + int rc; + sqlite3_stmt *s = *ppStmt; + assert( iStmtpFulltextStatements[iStmt] ); + + while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){ + if( rc==SQLITE_BUSY ) continue; + if( rc!=SQLITE_ERROR ) return rc; + + /* If an SQLITE_SCHEMA error has occured, then finalizing this + * statement is going to delete the fulltext_vtab structure. If + * the statement just executed is in the pFulltextStatements[] + * array, it will be finalized twice. So remove it before + * calling sqlite3_finalize(). + */ + v->pFulltextStatements[iStmt] = NULL; + rc = sqlite3_finalize(s); + break; + } + return rc; + + err: + sqlite3_finalize(s); + return rc; +} + +/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK. +** Useful for statements like UPDATE, where we expect no results. +*/ +static int sql_single_step_statement(fulltext_vtab *v, + fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + int rc = sql_step_statement(v, iStmt, ppStmt); + return (rc==SQLITE_DONE) ? SQLITE_OK : rc; +} + +/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */ +static int content_insert(fulltext_vtab *v, sqlite3_value *rowid, + sqlite3_value **pValues){ + sqlite3_stmt *s; + int i; + int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_value(s, 1, rowid); + if( rc!=SQLITE_OK ) return rc; + + for(i=0; inColumn; ++i){ + rc = sqlite3_bind_value(s, 2+i, pValues[i]); + if( rc!=SQLITE_OK ) return rc; + } + + return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s); +} + +/* update %_content set col0 = pValues[0], col1 = pValues[1], ... + * where rowid = [iRowid] */ +static int content_update(fulltext_vtab *v, sqlite3_value **pValues, + sqlite_int64 iRowid){ + sqlite3_stmt *s; + int i; + int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + for(i=0; inColumn; ++i){ + rc = sqlite3_bind_value(s, 1+i, pValues[i]); + if( rc!=SQLITE_OK ) return rc; + } + + rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, CONTENT_UPDATE_STMT, &s); +} + +static void freeStringArray(int nString, const char **pString){ + int i; + + for (i=0 ; i < nString ; ++i) { + if( pString[i]!=NULL ) free((void *) pString[i]); + } + free((void *) pString); +} + +/* select * from %_content where rowid = [iRow] + * The caller must delete the returned array and all strings in it. + * null fields will be NULL in the returned array. + * + * TODO: Perhaps we should return pointer/length strings here for consistency + * with other code which uses pointer/length. */ +static int content_select(fulltext_vtab *v, sqlite_int64 iRow, + const char ***pValues){ + sqlite3_stmt *s; + const char **values; + int i; + int rc; + + *pValues = NULL; + + rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s); + if( rc!=SQLITE_ROW ) return rc; + + values = (const char **) malloc(v->nColumn * sizeof(const char *)); + for(i=0; inColumn; ++i){ + if( sqlite3_column_type(s, i)==SQLITE_NULL ){ + values[i] = NULL; + }else{ + values[i] = string_dup((char*)sqlite3_column_text(s, i)); + } + } + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ){ + *pValues = values; + return SQLITE_OK; + } + + freeStringArray(v->nColumn, values); + return rc; +} + +/* delete from %_content where rowid = [iRow ] */ +static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iRow); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s); +} + +/* select rowid, doclist from %_term + * where term = [pTerm] and segment = [iSegment] + * If found, returns SQLITE_ROW; the caller must free the + * returned doclist. If no rows found, returns SQLITE_DONE. */ +static int term_select(fulltext_vtab *v, const char *pTerm, int nTerm, + int iSegment, + sqlite_int64 *rowid, DocList *out){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(s, 1, pTerm, nTerm, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 2, iSegment); + if( rc!=SQLITE_OK ) return rc; + + rc = sql_step_statement(v, TERM_SELECT_STMT, &s); + if( rc!=SQLITE_ROW ) return rc; + + *rowid = sqlite3_column_int64(s, 0); + docListInit(out, DL_DEFAULT, + sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1)); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + return rc==SQLITE_DONE ? SQLITE_ROW : rc; +} + +/* Load the segment doclists for term pTerm and merge them in +** appropriate order into out. Returns SQLITE_OK if successful. If +** there are no segments for pTerm, successfully returns an empty +** doclist in out. +** +** Each document consists of 1 or more "columns". The number of +** columns is v->nColumn. If iColumn==v->nColumn, then return +** position information about all columns. If iColumnnColumn, +** then only return position information about the iColumn-th column +** (where the first column is 0). +*/ +static int term_select_all( + fulltext_vtab *v, /* The fulltext index we are querying against */ + int iColumn, /* If nColumn ){ /* querying a single column */ + docListRestrictColumn(&old, iColumn); + } + + /* doclist contains the newer data, so write it over old. Then + ** steal accumulated result for doclist. + */ + docListAccumulate(&old, &doclist); + docListDestroy(&doclist); + doclist = old; + } + if( rc!=SQLITE_DONE ){ + docListDestroy(&doclist); + return rc; + } + + docListDiscardEmpty(&doclist); + *out = doclist; + return SQLITE_OK; +} + +/* insert into %_term (rowid, term, segment, doclist) + values ([piRowid], [pTerm], [iSegment], [doclist]) +** Lets sqlite select rowid if piRowid is NULL, else uses *piRowid. +** +** NOTE(shess) piRowid is IN, with values of "space of int64" plus +** null, it is not used to pass data back to the caller. +*/ +static int term_insert(fulltext_vtab *v, sqlite_int64 *piRowid, + const char *pTerm, int nTerm, + int iSegment, DocList *doclist){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + if( piRowid==NULL ){ + rc = sqlite3_bind_null(s, 1); + }else{ + rc = sqlite3_bind_int64(s, 1, *piRowid); + } + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(s, 2, pTerm, nTerm, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 3, iSegment); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 4, doclist->pData, doclist->nData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, TERM_INSERT_STMT, &s); +} + +/* update %_term set doclist = [doclist] where rowid = [rowid] */ +static int term_update(fulltext_vtab *v, sqlite_int64 rowid, + DocList *doclist){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, rowid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, TERM_UPDATE_STMT, &s); +} + +static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, rowid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, TERM_DELETE_STMT, &s); +} + +/* +** Free the memory used to contain a fulltext_vtab structure. +*/ +static void fulltext_vtab_destroy(fulltext_vtab *v){ + int iStmt, i; + + TRACE(("FTS1 Destroy %p\n", v)); + for( iStmt=0; iStmtpFulltextStatements[iStmt]!=NULL ){ + sqlite3_finalize(v->pFulltextStatements[iStmt]); + v->pFulltextStatements[iStmt] = NULL; + } + } + + if( v->pTokenizer!=NULL ){ + v->pTokenizer->pModule->xDestroy(v->pTokenizer); + v->pTokenizer = NULL; + } + + free(v->azColumn); + for(i = 0; i < v->nColumn; ++i) { + sqlite3_free(v->azContentColumn[i]); + } + free(v->azContentColumn); + free(v); +} + +/* +** Token types for parsing the arguments to xConnect or xCreate. +*/ +#define TOKEN_EOF 0 /* End of file */ +#define TOKEN_SPACE 1 /* Any kind of whitespace */ +#define TOKEN_ID 2 /* An identifier */ +#define TOKEN_STRING 3 /* A string literal */ +#define TOKEN_PUNCT 4 /* A single punctuation character */ + +/* +** If X is a character that can be used in an identifier then +** IdChar(X) will be true. Otherwise it is false. +** +** For ASCII, any character with the high-order bit set is +** allowed in an identifier. For 7-bit characters, +** sqlite3IsIdChar[X] must be 1. +** +** Ticket #1066. the SQL standard does not allow '$' in the +** middle of identfiers. But many SQL implementations do. +** SQLite will allow '$' in identifiers for compatibility. +** But the feature is undocumented. +*/ +static const char isIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20])) + + +/* +** Return the length of the token that begins at z[0]. +** Store the token type in *tokenType before returning. +*/ +static int getToken(const char *z, int *tokenType){ + int i, c; + switch( *z ){ + case 0: { + *tokenType = TOKEN_EOF; + return 0; + } + case ' ': case '\t': case '\n': case '\f': case '\r': { + for(i=1; safe_isspace(z[i]); i++){} + *tokenType = TOKEN_SPACE; + return i; + } + case '`': + case '\'': + case '"': { + int delim = z[0]; + for(i=1; (c=z[i])!=0; i++){ + if( c==delim ){ + if( z[i+1]==delim ){ + i++; + }else{ + break; + } + } + } + *tokenType = TOKEN_STRING; + return i + (c!=0); + } + case '[': { + for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} + *tokenType = TOKEN_ID; + return i; + } + default: { + if( !IdChar(*z) ){ + break; + } + for(i=1; IdChar(z[i]); i++){} + *tokenType = TOKEN_ID; + return i; + } + } + *tokenType = TOKEN_PUNCT; + return 1; +} + +/* +** A token extracted from a string is an instance of the following +** structure. +*/ +typedef struct Token { + const char *z; /* Pointer to token text. Not '\000' terminated */ + short int n; /* Length of the token text in bytes. */ +} Token; + +/* +** Given a input string (which is really one of the argv[] parameters +** passed into xConnect or xCreate) split the string up into tokens. +** Return an array of pointers to '\000' terminated strings, one string +** for each non-whitespace token. +** +** The returned array is terminated by a single NULL pointer. +** +** Space to hold the returned array is obtained from a single +** malloc and should be freed by passing the return value to free(). +** The individual strings within the token list are all a part of +** the single memory allocation and will all be freed at once. +*/ +static char **tokenizeString(const char *z, int *pnToken){ + int nToken = 0; + Token *aToken = malloc( strlen(z) * sizeof(aToken[0]) ); + int n = 1; + int e, i; + int totalSize = 0; + char **azToken; + char *zCopy; + while( n>0 ){ + n = getToken(z, &e); + if( e!=TOKEN_SPACE ){ + aToken[nToken].z = z; + aToken[nToken].n = n; + nToken++; + totalSize += n+1; + } + z += n; + } + azToken = (char**)malloc( nToken*sizeof(char*) + totalSize ); + zCopy = (char*)&azToken[nToken]; + nToken--; + for(i=0; i=0 ){ + azIn[j] = azIn[i]; + } + j++; + } + } + azIn[j] = 0; + } +} + + +/* +** Find the first alphanumeric token in the string zIn. Null-terminate +** this token. Remove any quotation marks. And return a pointer to +** the result. +*/ +static char *firstToken(char *zIn, char **pzTail){ + int n, ttype; + while(1){ + n = getToken(zIn, &ttype); + if( ttype==TOKEN_SPACE ){ + zIn += n; + }else if( ttype==TOKEN_EOF ){ + *pzTail = zIn; + return 0; + }else{ + zIn[n] = 0; + *pzTail = &zIn[1]; + dequoteString(zIn); + return zIn; + } + } + /*NOTREACHED*/ +} + +/* Return true if... +** +** * s begins with the string t, ignoring case +** * s is longer than t +** * The first character of s beyond t is not a alphanumeric +** +** Ignore leading space in *s. +** +** To put it another way, return true if the first token of +** s[] is t[]. +*/ +static int startsWith(const char *s, const char *t){ + while( safe_isspace(*s) ){ s++; } + while( *t ){ + if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0; + } + return *s!='_' && !safe_isalnum(*s); +} + +/* +** An instance of this structure defines the "spec" of a +** full text index. This structure is populated by parseSpec +** and use by fulltextConnect and fulltextCreate. +*/ +typedef struct TableSpec { + const char *zDb; /* Logical database name */ + const char *zName; /* Name of the full-text index */ + int nColumn; /* Number of columns to be indexed */ + char **azColumn; /* Original names of columns to be indexed */ + char **azContentColumn; /* Column names for %_content */ + char **azTokenizer; /* Name of tokenizer and its arguments */ +} TableSpec; + +/* +** Reclaim all of the memory used by a TableSpec +*/ +static void clearTableSpec(TableSpec *p) { + free(p->azColumn); + free(p->azContentColumn); + free(p->azTokenizer); +} + +/* Parse a CREATE VIRTUAL TABLE statement, which looks like this: + * + * CREATE VIRTUAL TABLE email + * USING fts1(subject, body, tokenize mytokenizer(myarg)) + * + * We return parsed information in a TableSpec structure. + * + */ +static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv, + char**pzErr){ + int i, n; + char *z, *zDummy; + char **azArg; + const char *zTokenizer = 0; /* argv[] entry describing the tokenizer */ + + assert( argc>=3 ); + /* Current interface: + ** argv[0] - module name + ** argv[1] - database name + ** argv[2] - table name + ** argv[3..] - columns, optionally followed by tokenizer specification + ** and snippet delimiters specification. + */ + + /* Make a copy of the complete argv[][] array in a single allocation. + ** The argv[][] array is read-only and transient. We can write to the + ** copy in order to modify things and the copy is persistent. + */ + memset(pSpec, 0, sizeof(*pSpec)); + for(i=n=0; izDb = azArg[1]; + pSpec->zName = azArg[2]; + pSpec->nColumn = 0; + pSpec->azColumn = azArg; + zTokenizer = "tokenize simple"; + for(i=3; inColumn] = firstToken(azArg[i], &zDummy); + pSpec->nColumn++; + } + } + if( pSpec->nColumn==0 ){ + azArg[0] = "content"; + pSpec->nColumn = 1; + } + + /* + ** Construct the list of content column names. + ** + ** Each content column name will be of the form cNNAAAA + ** where NN is the column number and AAAA is the sanitized + ** column name. "sanitized" means that special characters are + ** converted to "_". The cNN prefix guarantees that all column + ** names are unique. + ** + ** The AAAA suffix is not strictly necessary. It is included + ** for the convenience of people who might examine the generated + ** %_content table and wonder what the columns are used for. + */ + pSpec->azContentColumn = malloc( pSpec->nColumn * sizeof(char *) ); + if( pSpec->azContentColumn==0 ){ + clearTableSpec(pSpec); + return SQLITE_NOMEM; + } + for(i=0; inColumn; i++){ + char *p; + pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]); + for (p = pSpec->azContentColumn[i]; *p ; ++p) { + if( !safe_isalnum(*p) ) *p = '_'; + } + } + + /* + ** Parse the tokenizer specification string. + */ + pSpec->azTokenizer = tokenizeString(zTokenizer, &n); + tokenListToIdList(pSpec->azTokenizer); + + return SQLITE_OK; +} + +/* +** Generate a CREATE TABLE statement that describes the schema of +** the virtual table. Return a pointer to this schema string. +** +** Space is obtained from sqlite3_mprintf() and should be freed +** using sqlite3_free(). +*/ +static char *fulltextSchema( + int nColumn, /* Number of columns */ + const char *const* azColumn, /* List of columns */ + const char *zTableName /* Name of the table */ +){ + int i; + char *zSchema, *zNext; + const char *zSep = "("; + zSchema = sqlite3_mprintf("CREATE TABLE x"); + for(i=0; ibase */ + v->db = db; + v->zDb = spec->zDb; /* Freed when azColumn is freed */ + v->zName = spec->zName; /* Freed when azColumn is freed */ + v->nColumn = spec->nColumn; + v->azContentColumn = spec->azContentColumn; + spec->azContentColumn = 0; + v->azColumn = spec->azColumn; + spec->azColumn = 0; + + if( spec->azTokenizer==0 ){ + return SQLITE_NOMEM; + } + /* TODO(shess) For now, add new tokenizers as else if clauses. */ + if( spec->azTokenizer[0]==0 || startsWith(spec->azTokenizer[0], "simple") ){ + sqlite3Fts1SimpleTokenizerModule(&m); + }else if( startsWith(spec->azTokenizer[0], "porter") ){ + sqlite3Fts1PorterTokenizerModule(&m); + }else{ + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]); + rc = SQLITE_ERROR; + goto err; + } + for(n=0; spec->azTokenizer[n]; n++){} + if( n ){ + rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1], + &v->pTokenizer); + }else{ + rc = m->xCreate(0, 0, &v->pTokenizer); + } + if( rc!=SQLITE_OK ) goto err; + v->pTokenizer->pModule = m; + + /* TODO: verify the existence of backing tables foo_content, foo_term */ + + schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn, + spec->zName); + rc = sqlite3_declare_vtab(db, schema); + sqlite3_free(schema); + if( rc!=SQLITE_OK ) goto err; + + memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); + + *ppVTab = &v->base; + TRACE(("FTS1 Connect %p\n", v)); + + return rc; + +err: + fulltext_vtab_destroy(v); + return rc; +} + +static int fulltextConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, + char **pzErr +){ + TableSpec spec; + int rc = parseSpec(&spec, argc, argv, pzErr); + if( rc!=SQLITE_OK ) return rc; + + rc = constructVtab(db, &spec, ppVTab, pzErr); + clearTableSpec(&spec); + return rc; +} + + /* The %_content table holds the text of each document, with + ** the rowid used as the docid. + ** + ** The %_term table maps each term to a document list blob + ** containing elements sorted by ascending docid, each element + ** encoded as: + ** + ** docid varint-encoded + ** token elements: + ** position+1 varint-encoded as delta from previous position + ** start offset varint-encoded as delta from previous start offset + ** end offset varint-encoded as delta from start offset + ** + ** The sentinel position of 0 indicates the end of the token list. + ** + ** Additionally, doclist blobs are chunked into multiple segments, + ** using segment to order the segments. New elements are added to + ** the segment at segment 0, until it exceeds CHUNK_MAX. Then + ** segment 0 is deleted, and the doclist is inserted at segment 1. + ** If there is already a doclist at segment 1, the segment 0 doclist + ** is merged with it, the segment 1 doclist is deleted, and the + ** merged doclist is inserted at segment 2, repeating those + ** operations until an insert succeeds. + ** + ** Since this structure doesn't allow us to update elements in place + ** in case of deletion or update, these are simply written to + ** segment 0 (with an empty token list in case of deletion), with + ** docListAccumulate() taking care to retain lower-segment + ** information in preference to higher-segment information. + */ + /* TODO(shess) Provide a VACUUM type operation which both removes + ** deleted elements which are no longer necessary, and duplicated + ** elements. I suspect this will probably not be necessary in + ** practice, though. + */ +static int fulltextCreate(sqlite3 *db, void *pAux, + int argc, const char * const *argv, + sqlite3_vtab **ppVTab, char **pzErr){ + int rc; + TableSpec spec; + StringBuffer schema; + TRACE(("FTS1 Create\n")); + + rc = parseSpec(&spec, argc, argv, pzErr); + if( rc!=SQLITE_OK ) return rc; + + initStringBuffer(&schema); + append(&schema, "CREATE TABLE %_content("); + appendList(&schema, spec.nColumn, spec.azContentColumn); + append(&schema, ")"); + rc = sql_exec(db, spec.zDb, spec.zName, schema.s); + free(schema.s); + if( rc!=SQLITE_OK ) goto out; + + rc = sql_exec(db, spec.zDb, spec.zName, + "create table %_term(term text, segment integer, doclist blob, " + "primary key(term, segment));"); + if( rc!=SQLITE_OK ) goto out; + + rc = constructVtab(db, &spec, ppVTab, pzErr); + +out: + clearTableSpec(&spec); + return rc; +} + +/* Decide how to handle an SQL query. */ +static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ + int i; + TRACE(("FTS1 BestIndex\n")); + + for(i=0; inConstraint; ++i){ + const struct sqlite3_index_constraint *pConstraint; + pConstraint = &pInfo->aConstraint[i]; + if( pConstraint->usable ) { + if( pConstraint->iColumn==-1 && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + pInfo->idxNum = QUERY_ROWID; /* lookup by rowid */ + TRACE(("FTS1 QUERY_ROWID\n")); + } else if( pConstraint->iColumn>=0 && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ + /* full-text search */ + pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn; + TRACE(("FTS1 QUERY_FULLTEXT %d\n", pConstraint->iColumn)); + } else continue; + + pInfo->aConstraintUsage[i].argvIndex = 1; + pInfo->aConstraintUsage[i].omit = 1; + + /* An arbitrary value for now. + * TODO: Perhaps rowid matches should be considered cheaper than + * full-text searches. */ + pInfo->estimatedCost = 1.0; + + return SQLITE_OK; + } + } + pInfo->idxNum = QUERY_GENERIC; + return SQLITE_OK; +} + +static int fulltextDisconnect(sqlite3_vtab *pVTab){ + TRACE(("FTS1 Disconnect %p\n", pVTab)); + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextDestroy(sqlite3_vtab *pVTab){ + fulltext_vtab *v = (fulltext_vtab *)pVTab; + int rc; + + TRACE(("FTS1 Destroy %p\n", pVTab)); + rc = sql_exec(v->db, v->zDb, v->zName, + "drop table if exists %_content;" + "drop table if exists %_term;" + ); + if( rc!=SQLITE_OK ) return rc; + + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + fulltext_cursor *c; + + c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1); + /* sqlite will initialize c->base */ + *ppCursor = &c->base; + TRACE(("FTS1 Open %p: %p\n", pVTab, c)); + + return SQLITE_OK; +} + + +/* Free all of the dynamically allocated memory held by *q +*/ +static void queryClear(Query *q){ + int i; + for(i = 0; i < q->nTerms; ++i){ + free(q->pTerms[i].pTerm); + } + free(q->pTerms); + memset(q, 0, sizeof(*q)); +} + +/* Free all of the dynamically allocated memory held by the +** Snippet +*/ +static void snippetClear(Snippet *p){ + free(p->aMatch); + free(p->zOffset); + free(p->zSnippet); + memset(p, 0, sizeof(*p)); +} +/* +** Append a single entry to the p->aMatch[] log. +*/ +static void snippetAppendMatch( + Snippet *p, /* Append the entry to this snippet */ + int iCol, int iTerm, /* The column and query term */ + int iStart, int nByte /* Offset and size of the match */ +){ + int i; + struct snippetMatch *pMatch; + if( p->nMatch+1>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + 10; + p->aMatch = realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); + if( p->aMatch==0 ){ + p->nMatch = 0; + p->nAlloc = 0; + return; + } + } + i = p->nMatch++; + pMatch = &p->aMatch[i]; + pMatch->iCol = iCol; + pMatch->iTerm = iTerm; + pMatch->iStart = iStart; + pMatch->nByte = nByte; +} + +/* +** Sizing information for the circular buffer used in snippetOffsetsOfColumn() +*/ +#define FTS1_ROTOR_SZ (32) +#define FTS1_ROTOR_MASK (FTS1_ROTOR_SZ-1) + +/* +** Add entries to pSnippet->aMatch[] for every match that occurs against +** document zDoc[0..nDoc-1] which is stored in column iColumn. +*/ +static void snippetOffsetsOfColumn( + Query *pQuery, + Snippet *pSnippet, + int iColumn, + const char *zDoc, + int nDoc +){ + const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */ + sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */ + sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */ + fulltext_vtab *pVtab; /* The full text index */ + int nColumn; /* Number of columns in the index */ + const QueryTerm *aTerm; /* Query string terms */ + int nTerm; /* Number of query string terms */ + int i, j; /* Loop counters */ + int rc; /* Return code */ + unsigned int match, prevMatch; /* Phrase search bitmasks */ + const char *zToken; /* Next token from the tokenizer */ + int nToken; /* Size of zToken */ + int iBegin, iEnd, iPos; /* Offsets of beginning and end */ + + /* The following variables keep a circular buffer of the last + ** few tokens */ + unsigned int iRotor = 0; /* Index of current token */ + int iRotorBegin[FTS1_ROTOR_SZ]; /* Beginning offset of token */ + int iRotorLen[FTS1_ROTOR_SZ]; /* Length of token */ + + pVtab = pQuery->pFts; + nColumn = pVtab->nColumn; + pTokenizer = pVtab->pTokenizer; + pTModule = pTokenizer->pModule; + rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); + if( rc ) return; + pTCursor->pTokenizer = pTokenizer; + aTerm = pQuery->pTerms; + nTerm = pQuery->nTerms; + if( nTerm>=FTS1_ROTOR_SZ ){ + nTerm = FTS1_ROTOR_SZ - 1; + } + prevMatch = 0; + while(1){ + rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos); + if( rc ) break; + iRotorBegin[iRotor&FTS1_ROTOR_MASK] = iBegin; + iRotorLen[iRotor&FTS1_ROTOR_MASK] = iEnd-iBegin; + match = 0; + for(i=0; i=0 && iCol1 && (prevMatch & (1<=0; j--){ + int k = (iRotor-j) & FTS1_ROTOR_MASK; + snippetAppendMatch(pSnippet, iColumn, i-j, + iRotorBegin[k], iRotorLen[k]); + } + } + } + prevMatch = match<<1; + iRotor++; + } + pTModule->xClose(pTCursor); +} + + +/* +** Compute all offsets for the current row of the query. +** If the offsets have already been computed, this routine is a no-op. +*/ +static void snippetAllOffsets(fulltext_cursor *p){ + int nColumn; + int iColumn, i; + int iFirst, iLast; + fulltext_vtab *pFts; + + if( p->snippet.nMatch ) return; + if( p->q.nTerms==0 ) return; + pFts = p->q.pFts; + nColumn = pFts->nColumn; + iColumn = p->iCursorType - QUERY_FULLTEXT; + if( iColumn<0 || iColumn>=nColumn ){ + iFirst = 0; + iLast = nColumn-1; + }else{ + iFirst = iColumn; + iLast = iColumn; + } + for(i=iFirst; i<=iLast; i++){ + const char *zDoc; + int nDoc; + zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1); + nDoc = sqlite3_column_bytes(p->pStmt, i+1); + snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc); + } +} + +/* +** Convert the information in the aMatch[] array of the snippet +** into the string zOffset[0..nOffset-1]. +*/ +static void snippetOffsetText(Snippet *p){ + int i; + int cnt = 0; + StringBuffer sb; + char zBuf[200]; + if( p->zOffset ) return; + initStringBuffer(&sb); + for(i=0; inMatch; i++){ + struct snippetMatch *pMatch = &p->aMatch[i]; + zBuf[0] = ' '; + sprintf(&zBuf[cnt>0], "%d %d %d %d", pMatch->iCol, + pMatch->iTerm, pMatch->iStart, pMatch->nByte); + append(&sb, zBuf); + cnt++; + } + p->zOffset = sb.s; + p->nOffset = sb.len; +} + +/* +** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set +** of matching words some of which might be in zDoc. zDoc is column +** number iCol. +** +** iBreak is suggested spot in zDoc where we could begin or end an +** excerpt. Return a value similar to iBreak but possibly adjusted +** to be a little left or right so that the break point is better. +*/ +static int wordBoundary( + int iBreak, /* The suggested break point */ + const char *zDoc, /* Document text */ + int nDoc, /* Number of bytes in zDoc[] */ + struct snippetMatch *aMatch, /* Matching words */ + int nMatch, /* Number of entries in aMatch[] */ + int iCol /* The column number for zDoc[] */ +){ + int i; + if( iBreak<=10 ){ + return 0; + } + if( iBreak>=nDoc-10 ){ + return nDoc; + } + for(i=0; i0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ + return aMatch[i-1].iStart; + } + } + for(i=1; i<=10; i++){ + if( safe_isspace(zDoc[iBreak-i]) ){ + return iBreak - i + 1; + } + if( safe_isspace(zDoc[iBreak+i]) ){ + return iBreak + i + 1; + } + } + return iBreak; +} + +/* +** If the StringBuffer does not end in white space, add a single +** space character to the end. +*/ +static void appendWhiteSpace(StringBuffer *p){ + if( p->len==0 ) return; + if( safe_isspace(p->s[p->len-1]) ) return; + append(p, " "); +} + +/* +** Remove white space from teh end of the StringBuffer +*/ +static void trimWhiteSpace(StringBuffer *p){ + while( p->len>0 && safe_isspace(p->s[p->len-1]) ){ + p->len--; + } +} + + + +/* +** Allowed values for Snippet.aMatch[].snStatus +*/ +#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */ +#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */ + +/* +** Generate the text of a snippet. +*/ +static void snippetText( + fulltext_cursor *pCursor, /* The cursor we need the snippet for */ + const char *zStartMark, /* Markup to appear before each match */ + const char *zEndMark, /* Markup to appear after each match */ + const char *zEllipsis /* Ellipsis mark */ +){ + int i, j; + struct snippetMatch *aMatch; + int nMatch; + int nDesired; + StringBuffer sb; + int tailCol; + int tailOffset; + int iCol; + int nDoc; + const char *zDoc; + int iStart, iEnd; + int tailEllipsis = 0; + int iMatch; + + + free(pCursor->snippet.zSnippet); + pCursor->snippet.zSnippet = 0; + aMatch = pCursor->snippet.aMatch; + nMatch = pCursor->snippet.nMatch; + initStringBuffer(&sb); + + for(i=0; iq.nTerms; i++){ + for(j=0; j0; i++){ + if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue; + nDesired--; + iCol = aMatch[i].iCol; + zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1); + nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1); + iStart = aMatch[i].iStart - 40; + iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol); + if( iStart<=10 ){ + iStart = 0; + } + if( iCol==tailCol && iStart<=tailOffset+20 ){ + iStart = tailOffset; + } + if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ + trimWhiteSpace(&sb); + appendWhiteSpace(&sb); + append(&sb, zEllipsis); + appendWhiteSpace(&sb); + } + iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; + iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); + if( iEnd>=nDoc-10 ){ + iEnd = nDoc; + tailEllipsis = 0; + }else{ + tailEllipsis = 1; + } + while( iMatchsnippet.zSnippet = sb.s; + pCursor->snippet.nSnippet = sb.len; +} + + +/* +** Close the cursor. For additional information see the documentation +** on the xClose method of the virtual table interface. +*/ +static int fulltextClose(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + TRACE(("FTS1 Close %p\n", c)); + sqlite3_finalize(c->pStmt); + queryClear(&c->q); + snippetClear(&c->snippet); + if( c->result.pDoclist!=NULL ){ + docListDelete(c->result.pDoclist); + } + free(c); + return SQLITE_OK; +} + +static int fulltextNext(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + sqlite_int64 iDocid; + int rc; + + TRACE(("FTS1 Next %p\n", pCursor)); + snippetClear(&c->snippet); + if( c->iCursorType < QUERY_FULLTEXT ){ + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + switch( rc ){ + case SQLITE_ROW: + c->eof = 0; + return SQLITE_OK; + case SQLITE_DONE: + c->eof = 1; + return SQLITE_OK; + default: + c->eof = 1; + return rc; + } + } else { /* full-text query */ + rc = sqlite3_reset(c->pStmt); + if( rc!=SQLITE_OK ) return rc; + + iDocid = nextDocid(&c->result); + if( iDocid==0 ){ + c->eof = 1; + return SQLITE_OK; + } + rc = sqlite3_bind_int64(c->pStmt, 1, iDocid); + if( rc!=SQLITE_OK ) return rc; + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + if( rc==SQLITE_ROW ){ /* the case we expect */ + c->eof = 0; + return SQLITE_OK; + } + /* an error occurred; abort */ + return rc==SQLITE_DONE ? SQLITE_ERROR : rc; + } +} + + +/* Return a DocList corresponding to the query term *pTerm. If *pTerm +** is the first term of a phrase query, go ahead and evaluate the phrase +** query and return the doclist for the entire phrase query. +** +** The result is stored in pTerm->doclist. +*/ +static int docListOfTerm( + fulltext_vtab *v, /* The full text index */ + int iColumn, /* column to restrict to. No restrition if >=nColumn */ + QueryTerm *pQTerm, /* Term we are looking for, or 1st term of a phrase */ + DocList **ppResult /* Write the result here */ +){ + DocList *pLeft, *pRight, *pNew; + int i, rc; + + pLeft = docListNew(DL_POSITIONS); + rc = term_select_all(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pLeft); + if( rc ){ + docListDelete(pLeft); + return rc; + } + for(i=1; i<=pQTerm->nPhrase; i++){ + pRight = docListNew(DL_POSITIONS); + rc = term_select_all(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, pRight); + if( rc ){ + docListDelete(pLeft); + return rc; + } + pNew = docListNew(inPhrase ? DL_POSITIONS : DL_DOCIDS); + docListPhraseMerge(pLeft, pRight, pNew); + docListDelete(pLeft); + docListDelete(pRight); + pLeft = pNew; + } + *ppResult = pLeft; + return SQLITE_OK; +} + +/* Add a new term pTerm[0..nTerm-1] to the query *q. +*/ +static void queryAdd(Query *q, const char *pTerm, int nTerm){ + QueryTerm *t; + ++q->nTerms; + q->pTerms = realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0])); + if( q->pTerms==0 ){ + q->nTerms = 0; + return; + } + t = &q->pTerms[q->nTerms - 1]; + memset(t, 0, sizeof(*t)); + t->pTerm = malloc(nTerm+1); + memcpy(t->pTerm, pTerm, nTerm); + t->pTerm[nTerm] = 0; + t->nTerm = nTerm; + t->isOr = q->nextIsOr; + q->nextIsOr = 0; + t->iColumn = q->nextColumn; + q->nextColumn = q->dfltColumn; +} + +/* +** Check to see if the string zToken[0...nToken-1] matches any +** column name in the virtual table. If it does, +** return the zero-indexed column number. If not, return -1. +*/ +static int checkColumnSpecifier( + fulltext_vtab *pVtab, /* The virtual table */ + const char *zToken, /* Text of the token */ + int nToken /* Number of characters in the token */ +){ + int i; + for(i=0; inColumn; i++){ + if( memcmp(pVtab->azColumn[i], zToken, nToken)==0 + && pVtab->azColumn[i][nToken]==0 ){ + return i; + } + } + return -1; +} + +/* +** Parse the text at pSegment[0..nSegment-1]. Add additional terms +** to the query being assemblied in pQuery. +** +** inPhrase is true if pSegment[0..nSegement-1] is contained within +** double-quotes. If inPhrase is true, then the first term +** is marked with the number of terms in the phrase less one and +** OR and "-" syntax is ignored. If inPhrase is false, then every +** term found is marked with nPhrase=0 and OR and "-" syntax is significant. +*/ +static int tokenizeSegment( + sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */ + const char *pSegment, int nSegment, /* Query expression being parsed */ + int inPhrase, /* True if within "..." */ + Query *pQuery /* Append results here */ +){ + const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; + sqlite3_tokenizer_cursor *pCursor; + int firstIndex = pQuery->nTerms; + int iCol; + int nTerm = 1; + + int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); + if( rc!=SQLITE_OK ) return rc; + pCursor->pTokenizer = pTokenizer; + + while( 1 ){ + const char *pToken; + int nToken, iBegin, iEnd, iPos; + + rc = pModule->xNext(pCursor, + &pToken, &nToken, + &iBegin, &iEnd, &iPos); + if( rc!=SQLITE_OK ) break; + if( !inPhrase && + pSegment[iEnd]==':' && + (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ + pQuery->nextColumn = iCol; + continue; + } + if( !inPhrase && pQuery->nTerms>0 && nToken==2 + && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){ + pQuery->nextIsOr = 1; + continue; + } + queryAdd(pQuery, pToken, nToken); + if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ + pQuery->pTerms[pQuery->nTerms-1].isNot = 1; + } + pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm; + if( inPhrase ){ + nTerm++; + } + } + + if( inPhrase && pQuery->nTerms>firstIndex ){ + pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1; + } + + return pModule->xClose(pCursor); +} + +/* Parse a query string, yielding a Query object pQuery. +** +** The calling function will need to queryClear() to clean up +** the dynamically allocated memory held by pQuery. +*/ +static int parseQuery( + fulltext_vtab *v, /* The fulltext index */ + const char *zInput, /* Input text of the query string */ + int nInput, /* Size of the input text */ + int dfltColumn, /* Default column of the index to match against */ + Query *pQuery /* Write the parse results here. */ +){ + int iInput, inPhrase = 0; + + if( zInput==0 ) nInput = 0; + if( nInput<0 ) nInput = strlen(zInput); + pQuery->nTerms = 0; + pQuery->pTerms = NULL; + pQuery->nextIsOr = 0; + pQuery->nextColumn = dfltColumn; + pQuery->dfltColumn = dfltColumn; + pQuery->pFts = v; + + for(iInput=0; iInputiInput ){ + tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase, + pQuery); + } + iInput = i; + if( i=nColumn +** they are allowed to match against any column. +*/ +static int fulltextQuery( + fulltext_vtab *v, /* The full text index */ + int iColumn, /* Match against this column by default */ + const char *zInput, /* The query string */ + int nInput, /* Number of bytes in zInput[] */ + DocList **pResult, /* Write the result doclist here */ + Query *pQuery /* Put parsed query string here */ +){ + int i, iNext, rc; + DocList *pLeft = NULL; + DocList *pRight, *pNew, *pOr; + int nNot = 0; + QueryTerm *aTerm; + + rc = parseQuery(v, zInput, nInput, iColumn, pQuery); + if( rc!=SQLITE_OK ) return rc; + + /* Merge AND terms. */ + aTerm = pQuery->pTerms; + for(i = 0; inTerms; i=iNext){ + if( aTerm[i].isNot ){ + /* Handle all NOT terms in a separate pass */ + nNot++; + iNext = i + aTerm[i].nPhrase+1; + continue; + } + iNext = i + aTerm[i].nPhrase + 1; + rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &pRight); + if( rc ){ + queryClear(pQuery); + return rc; + } + while( iNextnTerms && aTerm[iNext].isOr ){ + rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &pOr); + iNext += aTerm[iNext].nPhrase + 1; + if( rc ){ + queryClear(pQuery); + return rc; + } + pNew = docListNew(DL_DOCIDS); + docListOrMerge(pRight, pOr, pNew); + docListDelete(pRight); + docListDelete(pOr); + pRight = pNew; + } + if( pLeft==0 ){ + pLeft = pRight; + }else{ + pNew = docListNew(DL_DOCIDS); + docListAndMerge(pLeft, pRight, pNew); + docListDelete(pRight); + docListDelete(pLeft); + pLeft = pNew; + } + } + + if( nNot && pLeft==0 ){ + /* We do not yet know how to handle a query of only NOT terms */ + return SQLITE_ERROR; + } + + /* Do the EXCEPT terms */ + for(i=0; inTerms; i += aTerm[i].nPhrase + 1){ + if( !aTerm[i].isNot ) continue; + rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &pRight); + if( rc ){ + queryClear(pQuery); + docListDelete(pLeft); + return rc; + } + pNew = docListNew(DL_DOCIDS); + docListExceptMerge(pLeft, pRight, pNew); + docListDelete(pRight); + docListDelete(pLeft); + pLeft = pNew; + } + + *pResult = pLeft; + return rc; +} + +/* +** This is the xFilter interface for the virtual table. See +** the virtual table xFilter method documentation for additional +** information. +** +** If idxNum==QUERY_GENERIC then do a full table scan against +** the %_content table. +** +** If idxNum==QUERY_ROWID then do a rowid lookup for a single entry +** in the %_content table. +** +** If idxNum>=QUERY_FULLTEXT then use the full text index. The +** column on the left-hand side of the MATCH operator is column +** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand +** side of the MATCH operator. +*/ +/* TODO(shess) Upgrade the cursor initialization and destruction to +** account for fulltextFilter() being called multiple times on the +** same cursor. The current solution is very fragile. Apply fix to +** fts2 as appropriate. +*/ +static int fulltextFilter( + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ + int idxNum, const char *idxStr, /* Which indexing scheme to use */ + int argc, sqlite3_value **argv /* Arguments for the indexing scheme */ +){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + fulltext_vtab *v = cursor_vtab(c); + int rc; + char *zSql; + + TRACE(("FTS1 Filter %p\n",pCursor)); + + zSql = sqlite3_mprintf("select rowid, * from %%_content %s", + idxNum==QUERY_GENERIC ? "" : "where rowid=?"); + sqlite3_finalize(c->pStmt); + rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, zSql); + sqlite3_free(zSql); + if( rc!=SQLITE_OK ) return rc; + + c->iCursorType = idxNum; + switch( idxNum ){ + case QUERY_GENERIC: + break; + + case QUERY_ROWID: + rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0])); + if( rc!=SQLITE_OK ) return rc; + break; + + default: /* full-text search */ + { + const char *zQuery = (const char *)sqlite3_value_text(argv[0]); + DocList *pResult; + assert( idxNum<=QUERY_FULLTEXT+v->nColumn); + assert( argc==1 ); + queryClear(&c->q); + rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &pResult, &c->q); + if( rc!=SQLITE_OK ) return rc; + if( c->result.pDoclist!=NULL ) docListDelete(c->result.pDoclist); + readerInit(&c->result, pResult); + break; + } + } + + return fulltextNext(pCursor); +} + +/* This is the xEof method of the virtual table. The SQLite core +** calls this routine to find out if it has reached the end of +** a query's results set. +*/ +static int fulltextEof(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + return c->eof; +} + +/* This is the xColumn method of the virtual table. The SQLite +** core calls this method during a query when it needs the value +** of a column from the virtual table. This method needs to use +** one of the sqlite3_result_*() routines to store the requested +** value back in the pContext. +*/ +static int fulltextColumn(sqlite3_vtab_cursor *pCursor, + sqlite3_context *pContext, int idxCol){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + fulltext_vtab *v = cursor_vtab(c); + + if( idxColnColumn ){ + sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); + sqlite3_result_value(pContext, pVal); + }else if( idxCol==v->nColumn ){ + /* The extra column whose name is the same as the table. + ** Return a blob which is a pointer to the cursor + */ + sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); + } + return SQLITE_OK; +} + +/* This is the xRowid method. The SQLite core calls this routine to +** retrive the rowid for the current row of the result set. The +** rowid should be written to *pRowid. +*/ +static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + + *pRowid = sqlite3_column_int64(c->pStmt, 0); + return SQLITE_OK; +} + +/* Add all terms in [zText] to the given hash table. If [iColumn] > 0, + * we also store positions and offsets in the hash table using the given + * column number. */ +static int buildTerms(fulltext_vtab *v, fts1Hash *terms, sqlite_int64 iDocid, + const char *zText, int iColumn){ + sqlite3_tokenizer *pTokenizer = v->pTokenizer; + sqlite3_tokenizer_cursor *pCursor; + const char *pToken; + int nTokenBytes; + int iStartOffset, iEndOffset, iPosition; + int rc; + + rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor); + if( rc!=SQLITE_OK ) return rc; + + pCursor->pTokenizer = pTokenizer; + while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor, + &pToken, &nTokenBytes, + &iStartOffset, &iEndOffset, + &iPosition) ){ + DocList *p; + + /* Positions can't be negative; we use -1 as a terminator internally. */ + if( iPosition<0 ){ + pTokenizer->pModule->xClose(pCursor); + return SQLITE_ERROR; + } + + p = fts1HashFind(terms, pToken, nTokenBytes); + if( p==NULL ){ + p = docListNew(DL_DEFAULT); + docListAddDocid(p, iDocid); + fts1HashInsert(terms, pToken, nTokenBytes, p); + } + if( iColumn>=0 ){ + docListAddPosOffset(p, iColumn, iPosition, iStartOffset, iEndOffset); + } + } + + /* TODO(shess) Check return? Should this be able to cause errors at + ** this point? Actually, same question about sqlite3_finalize(), + ** though one could argue that failure there means that the data is + ** not durable. *ponder* + */ + pTokenizer->pModule->xClose(pCursor); + return rc; +} + +/* Update the %_terms table to map the term [pTerm] to the given rowid. */ +static int index_insert_term(fulltext_vtab *v, const char *pTerm, int nTerm, + DocList *d){ + sqlite_int64 iIndexRow; + DocList doclist; + int iSegment = 0, rc; + + rc = term_select(v, pTerm, nTerm, iSegment, &iIndexRow, &doclist); + if( rc==SQLITE_DONE ){ + docListInit(&doclist, DL_DEFAULT, 0, 0); + docListUpdate(&doclist, d); + /* TODO(shess) Consider length(doclist)>CHUNK_MAX? */ + rc = term_insert(v, NULL, pTerm, nTerm, iSegment, &doclist); + goto err; + } + if( rc!=SQLITE_ROW ) return SQLITE_ERROR; + + docListUpdate(&doclist, d); + if( doclist.nData<=CHUNK_MAX ){ + rc = term_update(v, iIndexRow, &doclist); + goto err; + } + + /* Doclist doesn't fit, delete what's there, and accumulate + ** forward. + */ + rc = term_delete(v, iIndexRow); + if( rc!=SQLITE_OK ) goto err; + + /* Try to insert the doclist into a higher segment bucket. On + ** failure, accumulate existing doclist with the doclist from that + ** bucket, and put results in the next bucket. + */ + iSegment++; + while( (rc=term_insert(v, &iIndexRow, pTerm, nTerm, iSegment, + &doclist))!=SQLITE_OK ){ + sqlite_int64 iSegmentRow; + DocList old; + int rc2; + + /* Retain old error in case the term_insert() error was really an + ** error rather than a bounced insert. + */ + rc2 = term_select(v, pTerm, nTerm, iSegment, &iSegmentRow, &old); + if( rc2!=SQLITE_ROW ) goto err; + + rc = term_delete(v, iSegmentRow); + if( rc!=SQLITE_OK ) goto err; + + /* Reusing lowest-number deleted row keeps the index smaller. */ + if( iSegmentRownColumn ; ++i){ + char *zText = (char*)sqlite3_value_text(pValues[i]); + int rc = buildTerms(v, terms, iRowid, zText, i); + if( rc!=SQLITE_OK ) return rc; + } + return SQLITE_OK; +} + +/* Add empty doclists for all terms in the given row's content to the hash + * table [pTerms]. */ +static int deleteTerms(fulltext_vtab *v, fts1Hash *pTerms, sqlite_int64 iRowid){ + const char **pValues; + int i; + + int rc = content_select(v, iRowid, &pValues); + if( rc!=SQLITE_OK ) return rc; + + for(i = 0 ; i < v->nColumn; ++i) { + rc = buildTerms(v, pTerms, iRowid, pValues[i], -1); + if( rc!=SQLITE_OK ) break; + } + + freeStringArray(v->nColumn, pValues); + return SQLITE_OK; +} + +/* Insert a row into the %_content table; set *piRowid to be the ID of the + * new row. Fill [pTerms] with new doclists for the %_term table. */ +static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid, + sqlite3_value **pValues, + sqlite_int64 *piRowid, fts1Hash *pTerms){ + int rc; + + rc = content_insert(v, pRequestRowid, pValues); /* execute an SQL INSERT */ + if( rc!=SQLITE_OK ) return rc; + *piRowid = sqlite3_last_insert_rowid(v->db); + return insertTerms(v, pTerms, *piRowid, pValues); +} + +/* Delete a row from the %_content table; fill [pTerms] with empty doclists + * to be written to the %_term table. */ +static int index_delete(fulltext_vtab *v, sqlite_int64 iRow, fts1Hash *pTerms){ + int rc = deleteTerms(v, pTerms, iRow); + if( rc!=SQLITE_OK ) return rc; + return content_delete(v, iRow); /* execute an SQL DELETE */ +} + +/* Update a row in the %_content table; fill [pTerms] with new doclists for the + * %_term table. */ +static int index_update(fulltext_vtab *v, sqlite_int64 iRow, + sqlite3_value **pValues, fts1Hash *pTerms){ + /* Generate an empty doclist for each term that previously appeared in this + * row. */ + int rc = deleteTerms(v, pTerms, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = content_update(v, pValues, iRow); /* execute an SQL UPDATE */ + if( rc!=SQLITE_OK ) return rc; + + /* Now add positions for terms which appear in the updated row. */ + return insertTerms(v, pTerms, iRow, pValues); +} + +/* This function implements the xUpdate callback; it is the top-level entry + * point for inserting, deleting or updating a row in a full-text table. */ +static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, + sqlite_int64 *pRowid){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + fts1Hash terms; /* maps term string -> PosList */ + int rc; + fts1HashElem *e; + + TRACE(("FTS1 Update %p\n", pVtab)); + + fts1HashInit(&terms, FTS1_HASH_STRING, 1); + + if( nArg<2 ){ + rc = index_delete(v, sqlite3_value_int64(ppArg[0]), &terms); + } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){ + /* An update: + * ppArg[0] = old rowid + * ppArg[1] = new rowid + * ppArg[2..2+v->nColumn-1] = values + * ppArg[2+v->nColumn] = value for magic column (we ignore this) + */ + sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]); + if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER || + sqlite3_value_int64(ppArg[1]) != rowid ){ + rc = SQLITE_ERROR; /* we don't allow changing the rowid */ + } else { + assert( nArg==2+v->nColumn+1); + rc = index_update(v, rowid, &ppArg[2], &terms); + } + } else { + /* An insert: + * ppArg[1] = requested rowid + * ppArg[2..2+v->nColumn-1] = values + * ppArg[2+v->nColumn] = value for magic column (we ignore this) + */ + assert( nArg==2+v->nColumn+1); + rc = index_insert(v, ppArg[1], &ppArg[2], pRowid, &terms); + } + + if( rc==SQLITE_OK ){ + /* Write updated doclists to disk. */ + for(e=fts1HashFirst(&terms); e; e=fts1HashNext(e)){ + DocList *p = fts1HashData(e); + rc = index_insert_term(v, fts1HashKey(e), fts1HashKeysize(e), p); + if( rc!=SQLITE_OK ) break; + } + } + + /* clean up */ + for(e=fts1HashFirst(&terms); e; e=fts1HashNext(e)){ + DocList *p = fts1HashData(e); + docListDelete(p); + } + fts1HashClear(&terms); + + return rc; +} + +/* +** Implementation of the snippet() function for FTS1 +*/ +static void snippetFunc( + sqlite3_context *pContext, + int argc, + sqlite3_value **argv +){ + fulltext_cursor *pCursor; + if( argc<1 ) return; + if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || + sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ + sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1); + }else{ + const char *zStart = ""; + const char *zEnd = ""; + const char *zEllipsis = "..."; + memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); + if( argc>=2 ){ + zStart = (const char*)sqlite3_value_text(argv[1]); + if( argc>=3 ){ + zEnd = (const char*)sqlite3_value_text(argv[2]); + if( argc>=4 ){ + zEllipsis = (const char*)sqlite3_value_text(argv[3]); + } + } + } + snippetAllOffsets(pCursor); + snippetText(pCursor, zStart, zEnd, zEllipsis); + sqlite3_result_text(pContext, pCursor->snippet.zSnippet, + pCursor->snippet.nSnippet, SQLITE_STATIC); + } +} + +/* +** Implementation of the offsets() function for FTS1 +*/ +static void snippetOffsetsFunc( + sqlite3_context *pContext, + int argc, + sqlite3_value **argv +){ + fulltext_cursor *pCursor; + if( argc<1 ) return; + if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || + sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ + sqlite3_result_error(pContext, "illegal first argument to offsets",-1); + }else{ + memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); + snippetAllOffsets(pCursor); + snippetOffsetText(&pCursor->snippet); + sqlite3_result_text(pContext, + pCursor->snippet.zOffset, pCursor->snippet.nOffset, + SQLITE_STATIC); + } +} + +/* +** This routine implements the xFindFunction method for the FTS1 +** virtual table. +*/ +static int fulltextFindFunction( + sqlite3_vtab *pVtab, + int nArg, + const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg +){ + if( strcmp(zName,"snippet")==0 ){ + *pxFunc = snippetFunc; + return 1; + }else if( strcmp(zName,"offsets")==0 ){ + *pxFunc = snippetOffsetsFunc; + return 1; + } + return 0; +} + +/* +** Rename an fts1 table. +*/ +static int fulltextRename( + sqlite3_vtab *pVtab, + const char *zName +){ + fulltext_vtab *p = (fulltext_vtab *)pVtab; + int rc = SQLITE_NOMEM; + char *zSql = sqlite3_mprintf( + "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';" + "ALTER TABLE %Q.'%q_term' RENAME TO '%q_term';" + , p->zDb, p->zName, zName + , p->zDb, p->zName, zName + ); + if( zSql ){ + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } + return rc; +} + +static const sqlite3_module fulltextModule = { + /* iVersion */ 0, + /* xCreate */ fulltextCreate, + /* xConnect */ fulltextConnect, + /* xBestIndex */ fulltextBestIndex, + /* xDisconnect */ fulltextDisconnect, + /* xDestroy */ fulltextDestroy, + /* xOpen */ fulltextOpen, + /* xClose */ fulltextClose, + /* xFilter */ fulltextFilter, + /* xNext */ fulltextNext, + /* xEof */ fulltextEof, + /* xColumn */ fulltextColumn, + /* xRowid */ fulltextRowid, + /* xUpdate */ fulltextUpdate, + /* xBegin */ 0, + /* xSync */ 0, + /* xCommit */ 0, + /* xRollback */ 0, + /* xFindFunction */ fulltextFindFunction, + /* xRename */ fulltextRename, +}; + +int sqlite3Fts1Init(sqlite3 *db){ + sqlite3_overload_function(db, "snippet", -1); + sqlite3_overload_function(db, "offsets", -1); + return sqlite3_create_module(db, "fts1", &fulltextModule, 0); +} + +#if !SQLITE_CORE +int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, + const sqlite3_api_routines *pApi){ + SQLITE_EXTENSION_INIT2(pApi) + return sqlite3Fts1Init(db); +} +#endif + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.h new file mode 100644 index 0000000..d55e689 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1.h @@ -0,0 +1,11 @@ +#include "sqlite3.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int sqlite3Fts1Init(sqlite3 *db); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.c new file mode 100644 index 0000000..463a52b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.c @@ -0,0 +1,369 @@ +/* +** 2001 September 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 is the implementation of generic hash-tables used in SQLite. +** We've modified it slightly to serve as a standalone hash table +** implementation for the full-text indexing module. +*/ +#include +#include +#include + +/* +** The code in this file is only compiled if: +** +** * The FTS1 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS1 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS1 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) + + +#include "fts1_hash.h" + +static void *malloc_and_zero(int n){ + void *p = malloc(n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +** keyClass is one of the constants +** FTS1_HASH_BINARY or FTS1_HASH_STRING. The value of keyClass +** determines what kind of key the hash table will use. "copyKey" is +** true if the hash table should make its own private copy of keys and +** false if it should just use the supplied pointer. +*/ +void sqlite3Fts1HashInit(fts1Hash *pNew, int keyClass, int copyKey){ + assert( pNew!=0 ); + assert( keyClass>=FTS1_HASH_STRING && keyClass<=FTS1_HASH_BINARY ); + pNew->keyClass = keyClass; + pNew->copyKey = copyKey; + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; + pNew->xMalloc = malloc_and_zero; + pNew->xFree = free; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +void sqlite3Fts1HashClear(fts1Hash *pH){ + fts1HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + if( pH->ht ) pH->xFree(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + fts1HashElem *next_elem = elem->next; + if( pH->copyKey && elem->pKey ){ + pH->xFree(elem->pKey); + } + pH->xFree(elem); + elem = next_elem; + } + pH->count = 0; +} + +/* +** Hash and comparison functions when the mode is FTS1_HASH_STRING +*/ +static int strHash(const void *pKey, int nKey){ + const char *z = (const char *)pKey; + int h = 0; + if( nKey<=0 ) nKey = (int) strlen(z); + while( nKey > 0 ){ + h = (h<<3) ^ h ^ *z++; + nKey--; + } + return h & 0x7fffffff; +} +static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return strncmp((const char*)pKey1,(const char*)pKey2,n1); +} + +/* +** Hash and comparison functions when the mode is FTS1_HASH_BINARY +*/ +static int binHash(const void *pKey, int nKey){ + int h = 0; + const char *z = (const char *)pKey; + while( nKey-- > 0 ){ + h = (h<<3) ^ h ^ *(z++); + } + return h & 0x7fffffff; +} +static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return memcmp(pKey1,pKey2,n1); +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** The C syntax in this function definition may be unfamilar to some +** programmers, so we provide the following additional explanation: +** +** The name of the function is "hashFunction". The function takes a +** single parameter "keyClass". The return value of hashFunction() +** is a pointer to another function. Specifically, the return value +** of hashFunction() is a pointer to a function that takes two parameters +** with types "const void*" and "int" and returns an "int". +*/ +static int (*hashFunction(int keyClass))(const void*,int){ + if( keyClass==FTS1_HASH_STRING ){ + return &strHash; + }else{ + assert( keyClass==FTS1_HASH_BINARY ); + return &binHash; + } +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** For help in interpreted the obscure C code in the function definition, +** see the header comment on the previous function. +*/ +static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ + if( keyClass==FTS1_HASH_STRING ){ + return &strCompare; + }else{ + assert( keyClass==FTS1_HASH_BINARY ); + return &binCompare; + } +} + +/* Link an element into the hash table +*/ +static void insertElement( + fts1Hash *pH, /* The complete hash table */ + struct _fts1ht *pEntry, /* The entry into which pNew is inserted */ + fts1HashElem *pNew /* The element to be inserted */ +){ + fts1HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** "new_size" must be a power of 2. The hash table might fail +** to resize if sqliteMalloc() fails. +*/ +static void rehash(fts1Hash *pH, int new_size){ + struct _fts1ht *new_ht; /* The new hash table */ + fts1HashElem *elem, *next_elem; /* For looping over existing elements */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( (new_size & (new_size-1))==0 ); + new_ht = (struct _fts1ht *)pH->xMalloc( new_size*sizeof(struct _fts1ht) ); + if( new_ht==0 ) return; + if( pH->ht ) pH->xFree(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size; + xHash = hashFunction(pH->keyClass); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + next_elem = elem->next; + insertElement(pH, &new_ht[h], elem); + } +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. +*/ +static fts1HashElem *findElementGivenHash( + const fts1Hash *pH, /* The pH to be searched */ + const void *pKey, /* The key we are searching for */ + int nKey, + int h /* The hash for this key. */ +){ + fts1HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + int (*xCompare)(const void*,int,const void*,int); /* comparison function */ + + if( pH->ht ){ + struct _fts1ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + xCompare = compareFunction(pH->keyClass); + while( count-- && elem ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void removeElementGivenHash( + fts1Hash *pH, /* The pH containing "elem" */ + fts1HashElem* elem, /* The element to be removed from the pH */ + int h /* Hash value for the element */ +){ + struct _fts1ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; + } + if( pH->copyKey && elem->pKey ){ + pH->xFree(elem->pKey); + } + pH->xFree( elem ); + pH->count--; + if( pH->count<=0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + fts1HashClear(pH); + } +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +void *sqlite3Fts1HashFind(const fts1Hash *pH, const void *pKey, int nKey){ + int h; /* A hash on key */ + fts1HashElem *elem; /* The element that matches key */ + int (*xHash)(const void*,int); /* The hash function */ + + if( pH==0 || pH->ht==0 ) return 0; + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + h = (*xHash)(pKey,nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1)); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey,nKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created. A copy of the key is made if the copyKey +** flag is set. NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +void *sqlite3Fts1HashInsert( + fts1Hash *pH, /* The hash table to insert into */ + const void *pKey, /* The key */ + int nKey, /* Number of bytes in the key */ + void *data /* The data */ +){ + int hraw; /* Raw hash value of the key */ + int h; /* the hash of the key modulo hash table size */ + fts1HashElem *elem; /* Used to loop thru the element list */ + fts1HashElem *new_elem; /* New element added to the pH */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( pH!=0 ); + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + hraw = (*xHash)(pKey, nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + elem = findElementGivenHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + } + return old_data; + } + if( data==0 ) return 0; + new_elem = (fts1HashElem*)pH->xMalloc( sizeof(fts1HashElem) ); + if( new_elem==0 ) return data; + if( pH->copyKey && pKey!=0 ){ + new_elem->pKey = pH->xMalloc( nKey ); + if( new_elem->pKey==0 ){ + pH->xFree(new_elem); + return data; + } + memcpy((void*)new_elem->pKey, pKey, nKey); + }else{ + new_elem->pKey = (void*)pKey; + } + new_elem->nKey = nKey; + pH->count++; + if( pH->htsize==0 ){ + rehash(pH,8); + if( pH->htsize==0 ){ + pH->count = 0; + pH->xFree(new_elem); + return data; + } + } + if( pH->count > pH->htsize ){ + rehash(pH,pH->htsize*2); + } + assert( pH->htsize>0 ); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + insertElement(pH, &pH->ht[h], new_elem); + new_elem->data = data; + return 0; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.h new file mode 100644 index 0000000..c31c430 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_hash.h @@ -0,0 +1,112 @@ +/* +** 2001 September 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 is the header file for the generic hash-table implemenation +** used in SQLite. We've modified it slightly to serve as a standalone +** hash table implementation for the full-text indexing module. +** +*/ +#ifndef _FTS1_HASH_H_ +#define _FTS1_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct fts1Hash fts1Hash; +typedef struct fts1HashElem fts1HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct fts1Hash { + char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ + char copyKey; /* True if copy of key made on insert */ + int count; /* Number of entries in this table */ + fts1HashElem *first; /* The first element of the array */ + void *(*xMalloc)(int); /* malloc() function to use */ + void (*xFree)(void *); /* free() function to use */ + int htsize; /* Number of buckets in the hash table */ + struct _fts1ht { /* the hash table */ + int count; /* Number of entries with this hash */ + fts1HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct fts1HashElem { + fts1HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** There are 2 different modes of operation for a hash table: +** +** FTS1_HASH_STRING pKey points to a string that is nKey bytes long +** (including the null-terminator, if any). Case +** is respected in comparisons. +** +** FTS1_HASH_BINARY pKey points to binary data nKey bytes long. +** memcmp() is used to compare keys. +** +** A copy of the key is made if the copyKey parameter to fts1HashInit is 1. +*/ +#define FTS1_HASH_STRING 1 +#define FTS1_HASH_BINARY 2 + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +void sqlite3Fts1HashInit(fts1Hash*, int keytype, int copyKey); +void *sqlite3Fts1HashInsert(fts1Hash*, const void *pKey, int nKey, void *pData); +void *sqlite3Fts1HashFind(const fts1Hash*, const void *pKey, int nKey); +void sqlite3Fts1HashClear(fts1Hash*); + +/* +** Shorthand for the functions above +*/ +#define fts1HashInit sqlite3Fts1HashInit +#define fts1HashInsert sqlite3Fts1HashInsert +#define fts1HashFind sqlite3Fts1HashFind +#define fts1HashClear sqlite3Fts1HashClear + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** fts1Hash h; +** fts1HashElem *p; +** ... +** for(p=fts1HashFirst(&h); p; p=fts1HashNext(p)){ +** SomeStructure *pData = fts1HashData(p); +** // do something with pData +** } +*/ +#define fts1HashFirst(H) ((H)->first) +#define fts1HashNext(E) ((E)->next) +#define fts1HashData(E) ((E)->data) +#define fts1HashKey(E) ((E)->pKey) +#define fts1HashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define fts1HashCount(H) ((H)->count) + +#endif /* _FTS1_HASH_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_porter.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_porter.c new file mode 100644 index 0000000..1d26236 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_porter.c @@ -0,0 +1,643 @@ +/* +** 2006 September 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. +** +************************************************************************* +** Implementation of the full-text-search tokenizer that implements +** a Porter stemmer. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS1 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS1 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS1 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) + + +#include +#include +#include +#include +#include + +#include "fts1_tokenizer.h" + +/* +** Class derived from sqlite3_tokenizer +*/ +typedef struct porter_tokenizer { + sqlite3_tokenizer base; /* Base class */ +} porter_tokenizer; + +/* +** Class derived from sqlit3_tokenizer_cursor +*/ +typedef struct porter_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *zInput; /* input we are tokenizing */ + int nInput; /* size of the input */ + int iOffset; /* current position in zInput */ + int iToken; /* index of next token to be returned */ + char *zToken; /* storage for current token */ + int nAllocated; /* space allocated to zToken buffer */ +} porter_tokenizer_cursor; + + +/* Forward declaration */ +static const sqlite3_tokenizer_module porterTokenizerModule; + + +/* +** Create a new tokenizer instance. +*/ +static int porterCreate( + int argc, const char * const *argv, + sqlite3_tokenizer **ppTokenizer +){ + porter_tokenizer *t; + t = (porter_tokenizer *) calloc(sizeof(*t), 1); + if( t==NULL ) return SQLITE_NOMEM; + + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int porterDestroy(sqlite3_tokenizer *pTokenizer){ + free(pTokenizer); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is zInput[0..nInput-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int porterOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *zInput, int nInput, /* String to be tokenized */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + porter_tokenizer_cursor *c; + + c = (porter_tokenizer_cursor *) malloc(sizeof(*c)); + if( c==NULL ) return SQLITE_NOMEM; + + c->zInput = zInput; + if( zInput==0 ){ + c->nInput = 0; + }else if( nInput<0 ){ + c->nInput = (int)strlen(zInput); + }else{ + c->nInput = nInput; + } + c->iOffset = 0; /* start tokenizing at the beginning */ + c->iToken = 0; + c->zToken = NULL; /* no space allocated, yet. */ + c->nAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** porterOpen() above. +*/ +static int porterClose(sqlite3_tokenizer_cursor *pCursor){ + porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; + free(c->zToken); + free(c); + return SQLITE_OK; +} +/* +** Vowel or consonant +*/ +static const char cType[] = { + 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 2, 1 +}; + +/* +** isConsonant() and isVowel() determine if their first character in +** the string they point to is a consonant or a vowel, according +** to Porter ruls. +** +** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. +** 'Y' is a consonant unless it follows another consonant, +** in which case it is a vowel. +** +** In these routine, the letters are in reverse order. So the 'y' rule +** is that 'y' is a consonant unless it is followed by another +** consonent. +*/ +static int isVowel(const char*); +static int isConsonant(const char *z){ + int j; + char x = *z; + if( x==0 ) return 0; + assert( x>='a' && x<='z' ); + j = cType[x-'a']; + if( j<2 ) return j; + return z[1]==0 || isVowel(z + 1); +} +static int isVowel(const char *z){ + int j; + char x = *z; + if( x==0 ) return 0; + assert( x>='a' && x<='z' ); + j = cType[x-'a']; + if( j<2 ) return 1-j; + return isConsonant(z + 1); +} + +/* +** Let any sequence of one or more vowels be represented by V and let +** C be sequence of one or more consonants. Then every word can be +** represented as: +** +** [C] (VC){m} [V] +** +** In prose: A word is an optional consonant followed by zero or +** vowel-consonant pairs followed by an optional vowel. "m" is the +** number of vowel consonant pairs. This routine computes the value +** of m for the first i bytes of a word. +** +** Return true if the m-value for z is 1 or more. In other words, +** return true if z contains at least one vowel that is followed +** by a consonant. +** +** In this routine z[] is in reverse order. So we are really looking +** for an instance of of a consonant followed by a vowel. +*/ +static int m_gt_0(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* Like mgt0 above except we are looking for a value of m which is +** exactly 1 +*/ +static int m_eq_1(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + if( *z==0 ) return 0; + while( isVowel(z) ){ z++; } + if( *z==0 ) return 1; + while( isConsonant(z) ){ z++; } + return *z==0; +} + +/* Like mgt0 above except we are looking for a value of m>1 instead +** or m>0 +*/ +static int m_gt_1(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + if( *z==0 ) return 0; + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* +** Return TRUE if there is a vowel anywhere within z[0..n-1] +*/ +static int hasVowel(const char *z){ + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* +** Return TRUE if the word ends in a double consonant. +** +** The text is reversed here. So we are really looking at +** the first two characters of z[]. +*/ +static int doubleConsonant(const char *z){ + return isConsonant(z) && z[0]==z[1] && isConsonant(z+1); +} + +/* +** Return TRUE if the word ends with three letters which +** are consonant-vowel-consonent and where the final consonant +** is not 'w', 'x', or 'y'. +** +** The word is reversed here. So we are really checking the +** first three letters and the first one cannot be in [wxy]. +*/ +static int star_oh(const char *z){ + return + z[0]!=0 && isConsonant(z) && + z[0]!='w' && z[0]!='x' && z[0]!='y' && + z[1]!=0 && isVowel(z+1) && + z[2]!=0 && isConsonant(z+2); +} + +/* +** If the word ends with zFrom and xCond() is true for the stem +** of the word that preceeds the zFrom ending, then change the +** ending to zTo. +** +** The input word *pz and zFrom are both in reverse order. zTo +** is in normal order. +** +** Return TRUE if zFrom matches. Return FALSE if zFrom does not +** match. Not that TRUE is returned even if xCond() fails and +** no substitution occurs. +*/ +static int stem( + char **pz, /* The word being stemmed (Reversed) */ + const char *zFrom, /* If the ending matches this... (Reversed) */ + const char *zTo, /* ... change the ending to this (not reversed) */ + int (*xCond)(const char*) /* Condition that must be true */ +){ + char *z = *pz; + while( *zFrom && *zFrom==*z ){ z++; zFrom++; } + if( *zFrom!=0 ) return 0; + if( xCond && !xCond(z) ) return 1; + while( *zTo ){ + *(--z) = *(zTo++); + } + *pz = z; + return 1; +} + +/* +** This is the fallback stemmer used when the porter stemmer is +** inappropriate. The input word is copied into the output with +** US-ASCII case folding. If the input word is too long (more +** than 20 bytes if it contains no digits or more than 6 bytes if +** it contains digits) then word is truncated to 20 or 6 bytes +** by taking 10 or 3 bytes from the beginning and end. +*/ +static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ + int i, mx, j; + int hasDigit = 0; + for(i=0; i='A' && c<='Z' ){ + zOut[i] = c - 'A' + 'a'; + }else{ + if( c>='0' && c<='9' ) hasDigit = 1; + zOut[i] = c; + } + } + mx = hasDigit ? 3 : 10; + if( nIn>mx*2 ){ + for(j=mx, i=nIn-mx; i=sizeof(zReverse)-7 ){ + /* The word is too big or too small for the porter stemmer. + ** Fallback to the copy stemmer */ + copy_stemmer(zIn, nIn, zOut, pnOut); + return; + } + for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ + zReverse[j] = c + 'a' - 'A'; + }else if( c>='a' && c<='z' ){ + zReverse[j] = c; + }else{ + /* The use of a character not in [a-zA-Z] means that we fallback + ** to the copy stemmer */ + copy_stemmer(zIn, nIn, zOut, pnOut); + return; + } + } + memset(&zReverse[sizeof(zReverse)-5], 0, 5); + z = &zReverse[j+1]; + + + /* Step 1a */ + if( z[0]=='s' ){ + if( + !stem(&z, "sess", "ss", 0) && + !stem(&z, "sei", "i", 0) && + !stem(&z, "ss", "ss", 0) + ){ + z++; + } + } + + /* Step 1b */ + z2 = z; + if( stem(&z, "dee", "ee", m_gt_0) ){ + /* Do nothing. The work was all in the test */ + }else if( + (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) + && z!=z2 + ){ + if( stem(&z, "ta", "ate", 0) || + stem(&z, "lb", "ble", 0) || + stem(&z, "zi", "ize", 0) ){ + /* Do nothing. The work was all in the test */ + }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ + z++; + }else if( m_eq_1(z) && star_oh(z) ){ + *(--z) = 'e'; + } + } + + /* Step 1c */ + if( z[0]=='y' && hasVowel(z+1) ){ + z[0] = 'i'; + } + + /* Step 2 */ + switch( z[1] ){ + case 'a': + stem(&z, "lanoita", "ate", m_gt_0) || + stem(&z, "lanoit", "tion", m_gt_0); + break; + case 'c': + stem(&z, "icne", "ence", m_gt_0) || + stem(&z, "icna", "ance", m_gt_0); + break; + case 'e': + stem(&z, "rezi", "ize", m_gt_0); + break; + case 'g': + stem(&z, "igol", "log", m_gt_0); + break; + case 'l': + stem(&z, "ilb", "ble", m_gt_0) || + stem(&z, "illa", "al", m_gt_0) || + stem(&z, "iltne", "ent", m_gt_0) || + stem(&z, "ile", "e", m_gt_0) || + stem(&z, "ilsuo", "ous", m_gt_0); + break; + case 'o': + stem(&z, "noitazi", "ize", m_gt_0) || + stem(&z, "noita", "ate", m_gt_0) || + stem(&z, "rota", "ate", m_gt_0); + break; + case 's': + stem(&z, "msila", "al", m_gt_0) || + stem(&z, "ssenevi", "ive", m_gt_0) || + stem(&z, "ssenluf", "ful", m_gt_0) || + stem(&z, "ssensuo", "ous", m_gt_0); + break; + case 't': + stem(&z, "itila", "al", m_gt_0) || + stem(&z, "itivi", "ive", m_gt_0) || + stem(&z, "itilib", "ble", m_gt_0); + break; + } + + /* Step 3 */ + switch( z[0] ){ + case 'e': + stem(&z, "etaci", "ic", m_gt_0) || + stem(&z, "evita", "", m_gt_0) || + stem(&z, "ezila", "al", m_gt_0); + break; + case 'i': + stem(&z, "itici", "ic", m_gt_0); + break; + case 'l': + stem(&z, "laci", "ic", m_gt_0) || + stem(&z, "luf", "", m_gt_0); + break; + case 's': + stem(&z, "ssen", "", m_gt_0); + break; + } + + /* Step 4 */ + switch( z[1] ){ + case 'a': + if( z[0]=='l' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'c': + if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ + z += 4; + } + break; + case 'e': + if( z[0]=='r' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'i': + if( z[0]=='c' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'l': + if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ + z += 4; + } + break; + case 'n': + if( z[0]=='t' ){ + if( z[2]=='a' ){ + if( m_gt_1(z+3) ){ + z += 3; + } + }else if( z[2]=='e' ){ + stem(&z, "tneme", "", m_gt_1) || + stem(&z, "tnem", "", m_gt_1) || + stem(&z, "tne", "", m_gt_1); + } + } + break; + case 'o': + if( z[0]=='u' ){ + if( m_gt_1(z+2) ){ + z += 2; + } + }else if( z[3]=='s' || z[3]=='t' ){ + stem(&z, "noi", "", m_gt_1); + } + break; + case 's': + if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ + z += 3; + } + break; + case 't': + stem(&z, "eta", "", m_gt_1) || + stem(&z, "iti", "", m_gt_1); + break; + case 'u': + if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ + z += 3; + } + break; + case 'v': + case 'z': + if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ + z += 3; + } + break; + } + + /* Step 5a */ + if( z[0]=='e' ){ + if( m_gt_1(z+1) ){ + z++; + }else if( m_eq_1(z+1) && !star_oh(z+1) ){ + z++; + } + } + + /* Step 5b */ + if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ + z++; + } + + /* z[] is now the stemmed word in reverse order. Flip it back + ** around into forward order and return. + */ + *pnOut = i = strlen(z); + zOut[i] = 0; + while( *z ){ + zOut[--i] = *(z++); + } +} + +/* +** Characters that can be part of a token. We assume any character +** whose value is greater than 0x80 (any UTF character) can be +** part of a token. In other words, delimiters all must have +** values of 0x7f or lower. +*/ +static const char isIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define idChar(C) (((ch=C)&0x80)!=0 || (ch>0x2f && isIdChar[ch-0x30])) +#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !isIdChar[ch-0x30])) + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to porterOpen(). +*/ +static int porterNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ + const char **pzToken, /* OUT: *pzToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; + const char *z = c->zInput; + + while( c->iOffsetnInput ){ + int iStartOffset, ch; + + /* Scan past delimiter characters */ + while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ + c->iOffset++; + } + + /* Count non-delimiter characters. */ + iStartOffset = c->iOffset; + while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ + c->iOffset++; + } + + if( c->iOffset>iStartOffset ){ + int n = c->iOffset-iStartOffset; + if( n>c->nAllocated ){ + c->nAllocated = n+20; + c->zToken = realloc(c->zToken, c->nAllocated); + if( c->zToken==NULL ) return SQLITE_NOMEM; + } + porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); + *pzToken = c->zToken; + *piStartOffset = iStartOffset; + *piEndOffset = c->iOffset; + *piPosition = c->iToken++; + return SQLITE_OK; + } + } + return SQLITE_DONE; +} + +/* +** The set of routines that implement the porter-stemmer tokenizer +*/ +static const sqlite3_tokenizer_module porterTokenizerModule = { + 0, + porterCreate, + porterDestroy, + porterOpen, + porterClose, + porterNext, +}; + +/* +** Allocate a new porter tokenizer. Return a pointer to the new +** tokenizer in *ppModule +*/ +void sqlite3Fts1PorterTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &porterTokenizerModule; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer.h new file mode 100644 index 0000000..a48cb74 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer.h @@ -0,0 +1,90 @@ +/* +** 2006 July 10 +** +** The author disclaims copyright to this source code. +** +************************************************************************* +** Defines the interface to tokenizers used by fulltext-search. There +** are three basic components: +** +** sqlite3_tokenizer_module is a singleton defining the tokenizer +** interface functions. This is essentially the class structure for +** tokenizers. +** +** sqlite3_tokenizer is used to define a particular tokenizer, perhaps +** including customization information defined at creation time. +** +** sqlite3_tokenizer_cursor is generated by a tokenizer to generate +** tokens from a particular input. +*/ +#ifndef _FTS1_TOKENIZER_H_ +#define _FTS1_TOKENIZER_H_ + +/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. +** If tokenizers are to be allowed to call sqlite3_*() functions, then +** we will need a way to register the API consistently. +*/ +#include "sqlite3.h" + +/* +** Structures used by the tokenizer interface. +*/ +typedef struct sqlite3_tokenizer sqlite3_tokenizer; +typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; +typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; + +struct sqlite3_tokenizer_module { + int iVersion; /* currently 0 */ + + /* + ** Create and destroy a tokenizer. argc/argv are passed down from + ** the fulltext virtual table creation to allow customization. + */ + int (*xCreate)(int argc, const char *const*argv, + sqlite3_tokenizer **ppTokenizer); + int (*xDestroy)(sqlite3_tokenizer *pTokenizer); + + /* + ** Tokenize a particular input. Call xOpen() to prepare to + ** tokenize, xNext() repeatedly until it returns SQLITE_DONE, then + ** xClose() to free any internal state. The pInput passed to + ** xOpen() must exist until the cursor is closed. The ppToken + ** result from xNext() is only valid until the next call to xNext() + ** or until xClose() is called. + */ + /* TODO(shess) current implementation requires pInput to be + ** nul-terminated. This should either be fixed, or pInput/nBytes + ** should be converted to zInput. + */ + int (*xOpen)(sqlite3_tokenizer *pTokenizer, + const char *pInput, int nBytes, + sqlite3_tokenizer_cursor **ppCursor); + int (*xClose)(sqlite3_tokenizer_cursor *pCursor); + int (*xNext)(sqlite3_tokenizer_cursor *pCursor, + const char **ppToken, int *pnBytes, + int *piStartOffset, int *piEndOffset, int *piPosition); +}; + +struct sqlite3_tokenizer { + const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ + /* Tokenizer implementations will typically add additional fields */ +}; + +struct sqlite3_tokenizer_cursor { + sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ + /* Tokenizer implementations will typically add additional fields */ +}; + +/* +** Get the module for a tokenizer which generates tokens based on a +** set of non-token characters. The default is to break tokens at any +** non-alnum character, though the set of delimiters can also be +** specified by the first argv argument to xCreate(). +*/ +/* TODO(shess) This doesn't belong here. Need some sort of +** registration process. +*/ +void sqlite3Fts1SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); +void sqlite3Fts1PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); + +#endif /* _FTS1_TOKENIZER_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer1.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer1.c new file mode 100644 index 0000000..f58fba8 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fts1_tokenizer1.c @@ -0,0 +1,221 @@ +/* +** The author disclaims copyright to this source code. +** +************************************************************************* +** Implementation of the "simple" full-text-search tokenizer. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS1 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS1 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS1 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) + + +#include +#include +#include +#include +#include + +#include "fts1_tokenizer.h" + +typedef struct simple_tokenizer { + sqlite3_tokenizer base; + char delim[128]; /* flag ASCII delimiters */ +} simple_tokenizer; + +typedef struct simple_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *pInput; /* input we are tokenizing */ + int nBytes; /* size of the input */ + int iOffset; /* current position in pInput */ + int iToken; /* index of next token to be returned */ + char *pToken; /* storage for current token */ + int nTokenAllocated; /* space allocated to zToken buffer */ +} simple_tokenizer_cursor; + + +/* Forward declaration */ +static const sqlite3_tokenizer_module simpleTokenizerModule; + +static int isDelim(simple_tokenizer *t, unsigned char c){ + return c<0x80 && t->delim[c]; +} + +/* +** Create a new tokenizer instance. +*/ +static int simpleCreate( + int argc, const char * const *argv, + sqlite3_tokenizer **ppTokenizer +){ + simple_tokenizer *t; + + t = (simple_tokenizer *) calloc(sizeof(*t), 1); + if( t==NULL ) return SQLITE_NOMEM; + + /* TODO(shess) Delimiters need to remain the same from run to run, + ** else we need to reindex. One solution would be a meta-table to + ** track such information in the database, then we'd only want this + ** information on the initial create. + */ + if( argc>1 ){ + int i, n = strlen(argv[1]); + for(i=0; i=0x80 ){ + free(t); + return SQLITE_ERROR; + } + t->delim[ch] = 1; + } + } else { + /* Mark non-alphanumeric ASCII characters as delimiters */ + int i; + for(i=1; i<0x80; i++){ + t->delim[i] = !isalnum(i); + } + } + + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ + free(pTokenizer); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is pInput[0..nBytes-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int simpleOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *pInput, int nBytes, /* String to be tokenized */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + simple_tokenizer_cursor *c; + + c = (simple_tokenizer_cursor *) malloc(sizeof(*c)); + if( c==NULL ) return SQLITE_NOMEM; + + c->pInput = pInput; + if( pInput==0 ){ + c->nBytes = 0; + }else if( nBytes<0 ){ + c->nBytes = (int)strlen(pInput); + }else{ + c->nBytes = nBytes; + } + c->iOffset = 0; /* start tokenizing at the beginning */ + c->iToken = 0; + c->pToken = NULL; /* no space allocated, yet. */ + c->nTokenAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** simpleOpen() above. +*/ +static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + free(c->pToken); + free(c); + return SQLITE_OK; +} + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to simpleOpen(). +*/ +static int simpleNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ + const char **ppToken, /* OUT: *ppToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; + unsigned char *p = (unsigned char *)c->pInput; + + while( c->iOffsetnBytes ){ + int iStartOffset; + + /* Scan past delimiter characters */ + while( c->iOffsetnBytes && isDelim(t, p[c->iOffset]) ){ + c->iOffset++; + } + + /* Count non-delimiter characters. */ + iStartOffset = c->iOffset; + while( c->iOffsetnBytes && !isDelim(t, p[c->iOffset]) ){ + c->iOffset++; + } + + if( c->iOffset>iStartOffset ){ + int i, n = c->iOffset-iStartOffset; + if( n>c->nTokenAllocated ){ + c->nTokenAllocated = n+20; + c->pToken = realloc(c->pToken, c->nTokenAllocated); + if( c->pToken==NULL ) return SQLITE_NOMEM; + } + for(i=0; ipToken[i] = ch<0x80 ? tolower(ch) : ch; + } + *ppToken = c->pToken; + *pnBytes = n; + *piStartOffset = iStartOffset; + *piEndOffset = c->iOffset; + *piPosition = c->iToken++; + + return SQLITE_OK; + } + } + return SQLITE_DONE; +} + +/* +** The set of routines that implement the simple tokenizer +*/ +static const sqlite3_tokenizer_module simpleTokenizerModule = { + 0, + simpleCreate, + simpleDestroy, + simpleOpen, + simpleClose, + simpleNext, +}; + +/* +** Allocate a new simple tokenizer. Return a pointer to the new +** tokenizer in *ppModule +*/ +void sqlite3Fts1SimpleTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &simpleTokenizerModule; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS1) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.c new file mode 100644 index 0000000..e6034ba --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.c @@ -0,0 +1,1496 @@ +/* The author disclaims copyright to this source code. + * + * This is an SQLite module implementing full-text search. + */ + +#include +#if !defined(__APPLE__) +#include +#else +#include +#endif +#include +#include +#include + +#include "fulltext.h" +#include "ft_hash.h" +#include "tokenizer.h" +#include "sqlite3.h" +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + +/* utility functions */ + +/* We encode variable-length integers in little-endian order using seven bits + * per byte as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** and so on. +*/ + +/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */ +#define VARINT_MAX 10 + +/* Write a 64-bit variable-length integer to memory starting at p[0]. + * The length of data written will be between 1 and VARINT_MAX bytes. + * The number of bytes written is returned. */ +static int putVarint(char *p, sqlite_int64 v){ + unsigned char *q = (unsigned char *) p; + sqlite_uint64 vu = v; + do{ + *q++ = (unsigned char) ((vu & 0x7f) | 0x80); + vu >>= 7; + }while( vu!=0 ); + q[-1] &= 0x7f; /* turn off high bit in final byte */ + assert( q - (unsigned char *)p <= VARINT_MAX ); + return (int) (q - (unsigned char *)p); +} + +/* Read a 64-bit variable-length integer from memory starting at p[0]. + * Return the number of bytes read, or 0 on error. + * The value is stored in *v. */ +static int getVarint(const char *p, sqlite_int64 *v){ + const unsigned char *q = (const unsigned char *) p; + sqlite_uint64 x = 0, y = 1; + while( (*q & 0x80) == 0x80 ){ + x += y * (*q++ & 0x7f); + y <<= 7; + if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */ + assert( 0 ); + return 0; + } + } + x += y * (*q++); + *v = (sqlite_int64) x; + return (int) (q - (unsigned char *)p); +} + +static int getVarint32(const char *p, int *pi){ + sqlite_int64 i; + int ret = getVarint(p, &i); + *pi = (int) i; + assert( *pi==i ); + return ret; +} + +/*** Document lists *** + * + * A document list holds a sorted list of varint-encoded document IDs. + * + * A doclist with type DL_POSITIONS_OFFSETS is stored like this: + * + * array { + * varint docid; + * array { + * varint position; (delta from previous position plus 1, or 0 for end) + * varint startOffset; (delta from previous startOffset) + * varint endOffset; (delta from startOffset) + * } + * } + * + * Here, array { X } means zero or more occurrences of X, adjacent in memory. + * + * A doclist with type DL_POSITIONS is like the above, but holds only docids + * and positions without offset information. + * + * A doclist with type DL_DOCIDS is like the above, but holds only docids + * without positions or offset information. + * + * On disk, every document list has positions and offsets, so we don't bother + * to serialize a doclist's type. + * + * We don't yet delta-encode document IDs; doing so will probably be a + * modest win. + * + * NOTE(shess) I've thought of a slightly (1%) better offset encoding. + * After the first offset, estimate the next offset by using the + * current token position and the previous token position and offset, + * offset to handle some variance. So the estimate would be + * (iPosition*w->iStartOffset/w->iPosition-64), which is delta-encoded + * as normal. Offsets more than 64 chars from the estimate are + * encoded as the delta to the previous start offset + 128. An + * additional tiny increment can be gained by using the end offset of + * the previous token to make the estimate a tiny bit more precise. +*/ + +typedef enum DocListType { + DL_DOCIDS, /* docids only */ + DL_POSITIONS, /* docids + positions */ + DL_POSITIONS_OFFSETS /* docids + positions + offsets */ +} DocListType; + +typedef struct DocList { + char *pData; + int nData; + DocListType iType; + int iLastPos; /* the last position written */ + int iLastOffset; /* the last start offset written */ +} DocList; + +/* Initialize a new DocList to hold the given data. */ +static void docListInit(DocList *d, DocListType iType, + const char *pData, int nData){ + d->nData = nData; + if( nData>0 ){ + d->pData = malloc(nData); + memcpy(d->pData, pData, nData); + } else { + d->pData = NULL; + } + d->iType = iType; + d->iLastPos = 0; + d->iLastOffset = 0; +} + +/* Create a new dynamically-allocated DocList. */ +static DocList *docListNew(DocListType iType){ + DocList *d = (DocList *) malloc(sizeof(DocList)); + docListInit(d, iType, 0, 0); + return d; +} + +static void docListDestroy(DocList *d){ + free(d->pData); +#ifndef NDEBUG + memset(d, 0x55, sizeof(*d)); +#endif +} + +static void docListDelete(DocList *d){ + docListDestroy(d); + free(d); +} + +static char *docListEnd(DocList *d){ + return d->pData + d->nData; +} + +/* Append a varint to a DocList's data. */ +static void appendVarint(DocList *d, sqlite_int64 i){ + char c[VARINT_MAX]; + int n = putVarint(c, i); + d->pData = realloc(d->pData, d->nData + n); + memcpy(d->pData + d->nData, c, n); + d->nData += n; +} + +static void docListAddDocid(DocList *d, sqlite_int64 iDocid){ + appendVarint(d, iDocid); + d->iLastPos = 0; +} + +/* Add a position to the last position list in a doclist. */ +static void docListAddPos(DocList *d, int iPos){ + assert( d->iType>=DL_POSITIONS ); + appendVarint(d, iPos-d->iLastPos+1); + d->iLastPos = iPos; +} + +static void docListAddPosOffset(DocList *d, int iPos, + int iStartOffset, int iEndOffset){ + assert( d->iType==DL_POSITIONS_OFFSETS ); + docListAddPos(d, iPos); + appendVarint(d, iStartOffset-d->iLastOffset); + d->iLastOffset = iStartOffset; + appendVarint(d, iEndOffset-iStartOffset); +} + +/* Terminate the last position list in the given doclist. */ +static void docListAddEndPos(DocList *d){ + appendVarint(d, 0); +} + +typedef struct DocListReader { + DocList *pDoclist; + char *p; + int iLastPos; /* the last position read */ +} DocListReader; + +static void readerInit(DocListReader *r, DocList *pDoclist){ + r->pDoclist = pDoclist; + if( pDoclist!=NULL ){ + r->p = pDoclist->pData; + } + r->iLastPos = 0; +} + +static int readerAtEnd(DocListReader *pReader){ + return pReader->p >= docListEnd(pReader->pDoclist); +} + +/* Peek at the next docid without advancing the read pointer. */ +static sqlite_int64 peekDocid(DocListReader *pReader){ + sqlite_int64 ret; + assert( !readerAtEnd(pReader) ); + getVarint(pReader->p, &ret); + return ret; +} + +/* Read the next docid. */ +static sqlite_int64 readDocid(DocListReader *pReader){ + sqlite_int64 ret; + assert( !readerAtEnd(pReader) ); + pReader->p += getVarint(pReader->p, &ret); + pReader->iLastPos = 0; + return ret; +} + +/* Read the next position from a position list. + * Returns the position, or -1 at the end of the list. */ +static int readPosition(DocListReader *pReader){ + int i; + int iType = pReader->pDoclist->iType; + assert( iType>=DL_POSITIONS ); + assert( !readerAtEnd(pReader) ); + + pReader->p += getVarint32(pReader->p, &i); + if( i==0 ){ + pReader->iLastPos = -1; + return -1; + } + pReader->iLastPos += ((int) i)-1; + if( iType>=DL_POSITIONS_OFFSETS ){ + /* Skip over offsets, ignoring them for now. */ + int iStart, iEnd; + pReader->p += getVarint32(pReader->p, &iStart); + pReader->p += getVarint32(pReader->p, &iEnd); + } + return pReader->iLastPos; +} + +/* Skip past the end of a position list. */ +static void skipPositionList(DocListReader *pReader){ + while( readPosition(pReader)!=-1 ) + ; +} + +/* Skip over a docid, including its position list if the doclist has + * positions. */ +static void skipDocument(DocListReader *pReader){ + readDocid(pReader); + if( pReader->pDoclist->iType >= DL_POSITIONS ){ + skipPositionList(pReader); + } +} + +static sqlite_int64 firstDocid(DocList *d){ + DocListReader r; + readerInit(&r, d); + return readDocid(&r); +} + +/* Doclist multi-tool. Pass pUpdate==NULL to delete the indicated docid; + * otherwise pUpdate, which must contain only the single docid [iDocid], is + * inserted (if not present) or updated (if already present). */ +static int docListUpdate(DocList *d, sqlite_int64 iDocid, DocList *pUpdate){ + int modified = 0; + DocListReader reader; + char *p; + + if( pUpdate!=NULL ){ + assert( d->iType==pUpdate->iType); + assert( iDocid==firstDocid(pUpdate) ); + } + + readerInit(&reader, d); + while( !readerAtEnd(&reader) && peekDocid(&reader)nData -= (reader.p - p); + modified = 1; + } + + /* Insert if indicated. */ + if( pUpdate!=NULL ){ + int iDoclist = p-d->pData; + docListAddEndPos(pUpdate); + + d->pData = realloc(d->pData, d->nData+pUpdate->nData); + p = d->pData + iDoclist; + + memmove(p+pUpdate->nData, p, docListEnd(d) - p); + memcpy(p, pUpdate->pData, pUpdate->nData); + d->nData += pUpdate->nData; + modified = 1; + } + + return modified; +} + +/* Split the second half of doclist d into a separate doclist d2. Returns 1 + * if successful, or 0 if d contains a single document and hence can't be + * split. */ +static int docListSplit(DocList *d, DocList *d2){ + const char *pSplitPoint = d->pData + d->nData / 2; + DocListReader reader; + + readerInit(&reader, d); + while( reader.piType, reader.p, docListEnd(d) - reader.p); + d->nData = reader.p - d->pData; + d->pData = realloc(d->pData, d->nData); + return 1; +} + +/* A DocListMerge computes the AND of an in-memory DocList [in] and a chunked + * on-disk doclist, resulting in another in-memory DocList [out]. [in] + * and [out] may or may not store position information according to the + * caller's wishes. The on-disk doclist always comes with positions. + * + * The caller must read each chunk of the on-disk doclist in succession and + * pass it to mergeBlock(). + * + * If [in] has positions, then the merge output contains only documents with + * matching positions in the two input doclists. If [in] does not have + * positions, then the merge output contains all documents common to the two + * input doclists. + * + * If [in] is NULL, then the on-disk doclist is copied to [out] directly. + * + * A merge is performed using an integer [iOffset] provided by the caller. + * [iOffset] is subtracted from each position in the on-disk doclist for the + * purpose of position comparison; this is helpful in implementing phrase + * searches. + * + * A DocListMerge is not yet able to propagate offsets through query + * processing; we should add that capability soon. +*/ +typedef struct DocListMerge { + DocListReader in; + DocList *pOut; + int iOffset; +} DocListMerge; + +static void mergeInit(DocListMerge *m, + DocList *pIn, int iOffset, DocList *pOut){ + readerInit(&m->in, pIn); + m->pOut = pOut; + m->iOffset = iOffset; + + /* can't handle offsets yet */ + assert( pIn==NULL || pIn->iType <= DL_POSITIONS ); + assert( pOut->iType <= DL_POSITIONS ); +} + +/* A helper function for mergeBlock(), below. Merge the position lists + * pointed to by m->in and pBlockReader. + * If the merge matches, write [iDocid] to m->pOut; if m->pOut + * has positions then write all matching positions as well. */ +static void mergePosList(DocListMerge *m, sqlite_int64 iDocid, + DocListReader *pBlockReader){ + int block_pos = readPosition(pBlockReader); + int in_pos = readPosition(&m->in); + int match = 0; + while( block_pos!=-1 || in_pos!=-1 ){ + if( block_pos-m->iOffset==in_pos ){ + if( !match ){ + docListAddDocid(m->pOut, iDocid); + match = 1; + } + if( m->pOut->iType >= DL_POSITIONS ){ + docListAddPos(m->pOut, in_pos); + } + block_pos = readPosition(pBlockReader); + in_pos = readPosition(&m->in); + } else if( in_pos==-1 || (block_pos!=-1 && block_pos-m->iOffsetin); + } + } + if( m->pOut->iType >= DL_POSITIONS && match ){ + docListAddEndPos(m->pOut); + } +} + +/* Merge one block of an on-disk doclist into a DocListMerge. */ +static void mergeBlock(DocListMerge *m, DocList *pBlock){ + DocListReader blockReader; + assert( pBlock->iType >= DL_POSITIONS ); + readerInit(&blockReader, pBlock); + while( !readerAtEnd(&blockReader) ){ + sqlite_int64 iDocid = readDocid(&blockReader); + if( m->in.pDoclist!=NULL ){ + while( 1 ){ + if( readerAtEnd(&m->in) ) return; /* nothing more to merge */ + if( peekDocid(&m->in)>=iDocid ) break; + skipDocument(&m->in); + } + if( peekDocid(&m->in)>iDocid ){ /* [pIn] has no match with iDocid */ + skipPositionList(&blockReader); /* skip this docid in the block */ + continue; + } + readDocid(&m->in); + } + /* We have a document match. */ + if( m->in.pDoclist==NULL || m->in.pDoclist->iType < DL_POSITIONS ){ + /* We don't need to do a poslist merge. */ + docListAddDocid(m->pOut, iDocid); + if( m->pOut->iType >= DL_POSITIONS ){ + /* Copy all positions to the output doclist. */ + while( 1 ){ + int pos = readPosition(&blockReader); + if( pos==-1 ) break; + docListAddPos(m->pOut, pos); + } + docListAddEndPos(m->pOut); + } else skipPositionList(&blockReader); + continue; + } + mergePosList(m, iDocid, &blockReader); + } +} + +static char *string_dup_n(const char *s, int n){ + char *str = malloc(n + 1); + memcpy(str, s, n); + str[n] = '\0'; + return str; +} + +/* Duplicate a string; the caller must free() the returned string. + * (We don't use strdup() since it's not part of the standard C library and + * may not be available everywhere.) */ +static char *string_dup(const char *s){ + return string_dup_n(s, strlen(s)); +} + +/* Format a string, replacing each occurrence of the % character with + * zName. This may be more convenient than sqlite_mprintf() + * when one string is used repeatedly in a format string. + * The caller must free() the returned string. */ +static char *string_format(const char *zFormat, const char *zName){ + const char *p; + size_t len = 0; + size_t nName = strlen(zName); + char *result; + char *r; + + /* first compute length needed */ + for(p = zFormat ; *p ; ++p){ + len += (*p=='%' ? nName : 1); + } + len += 1; /* for null terminator */ + + r = result = malloc(len); + for(p = zFormat; *p; ++p){ + if( *p=='%' ){ + memcpy(r, zName, nName); + r += nName; + } else { + *r++ = *p; + } + } + *r++ = '\0'; + assert( r == result + len ); + return result; +} + +static int sql_exec(sqlite3 *db, const char *zName, const char *zFormat){ + char *zCommand = string_format(zFormat, zName); + int rc = sqlite3_exec(db, zCommand, NULL, 0, NULL); + free(zCommand); + return rc; +} + +static int sql_prepare(sqlite3 *db, const char *zName, sqlite3_stmt **ppStmt, + const char *zFormat){ + char *zCommand = string_format(zFormat, zName); + int rc = sqlite3_prepare(db, zCommand, -1, ppStmt, NULL); + free(zCommand); + return rc; +} + +/* end utility functions */ + +#define QUERY_GENERIC 0 +#define QUERY_FULLTEXT 1 + +#define CHUNK_MAX 1024 + +typedef enum fulltext_statement { + CONTENT_INSERT_STMT, + CONTENT_SELECT_STMT, + CONTENT_DELETE_STMT, + + TERM_SELECT_STMT, + TERM_CHUNK_SELECT_STMT, + TERM_INSERT_STMT, + TERM_UPDATE_STMT, + TERM_DELETE_STMT, + + MAX_STMT /* Always at end! */ +} fulltext_statement; + +/* These must exactly match the enum above. */ +/* TODO(adam): Is there some risk that a statement (in particular, +** pTermSelectStmt) will be used in two cursors at once, e.g. if a +** query joins a virtual table to itself? If so perhaps we should +** move some of these to the cursor object. +*/ +static const char *fulltext_zStatement[MAX_STMT] = { + /* CONTENT_INSERT */ "insert into %_content (rowid, content) values (?, ?)", + /* CONTENT_SELECT */ "select content from %_content where rowid = ?", + /* CONTENT_DELETE */ "delete from %_content where rowid = ?", + + /* TERM_SELECT */ + "select rowid, doclist from %_term where term = ? and first = ?", + /* TERM_CHUNK_SELECT */ + "select max(first) from %_term where term = ? and first <= ?", + /* TERM_INSERT */ + "insert into %_term (term, first, doclist) values (?, ?, ?)", + /* TERM_UPDATE */ "update %_term set doclist = ? where rowid = ?", + /* TERM_DELETE */ "delete from %_term where rowid = ?", +}; + +typedef struct fulltext_vtab { + sqlite3_vtab base; + sqlite3 *db; + const char *zName; /* virtual table name */ + sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ + + /* Precompiled statements which we keep as long as the table is + ** open. + */ + sqlite3_stmt *pFulltextStatements[MAX_STMT]; +} fulltext_vtab; + +typedef struct fulltext_cursor { + sqlite3_vtab_cursor base; + int iCursorType; /* QUERY_GENERIC or QUERY_FULLTEXT */ + + sqlite3_stmt *pStmt; + + int eof; + + /* The following is used only when iCursorType == QUERY_FULLTEXT. */ + DocListReader result; +} fulltext_cursor; + +static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){ + return (fulltext_vtab *) c->base.pVtab; +} + +static sqlite3_module fulltextModule; /* forward declaration */ + +/* Puts a freshly-prepared statement determined by iStmt in *ppStmt. +** If the indicated statement has never been prepared, it is prepared +** and cached, otherwise the cached version is reset. +*/ +static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + assert( iStmtpFulltextStatements[iStmt]==NULL ){ + int rc = sql_prepare(v->db, v->zName, &v->pFulltextStatements[iStmt], + fulltext_zStatement[iStmt]); + if( rc!=SQLITE_OK ) return rc; + } else { + int rc = sqlite3_reset(v->pFulltextStatements[iStmt]); + if( rc!=SQLITE_OK ) return rc; + } + + *ppStmt = v->pFulltextStatements[iStmt]; + return SQLITE_OK; +} + +/* Step the indicated statement, handling errors SQLITE_BUSY (by +** retrying) and SQLITE_SCHEMA (by re-preparing and transferring +** bindings to the new statement). +** TODO(adam): We should extend this function so that it can work with +** statements declared locally, not only globally cached statements. +*/ +static int sql_step_statement(fulltext_vtab *v, fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + int rc; + sqlite3_stmt *s = *ppStmt; + assert( iStmtpFulltextStatements[iStmt] ); + + while( (rc=sqlite3_step(s))!=SQLITE_DONE && rc!=SQLITE_ROW ){ + sqlite3_stmt *pNewStmt; + + if( rc==SQLITE_BUSY ) continue; + if( rc!=SQLITE_ERROR ) return rc; + + rc = sqlite3_reset(s); + if( rc!=SQLITE_SCHEMA ) return SQLITE_ERROR; + + v->pFulltextStatements[iStmt] = NULL; /* Still in s */ + rc = sql_get_statement(v, iStmt, &pNewStmt); + if( rc!=SQLITE_OK ) goto err; + *ppStmt = pNewStmt; + + rc = sqlite3_transfer_bindings(s, pNewStmt); + if( rc!=SQLITE_OK ) goto err; + + rc = sqlite3_finalize(s); + if( rc!=SQLITE_OK ) return rc; + s = pNewStmt; + } + return rc; + + err: + sqlite3_finalize(s); + return rc; +} + +/* Like sql_step_statement(), but convert SQLITE_DONE to SQLITE_OK. +** Useful for statements like UPDATE, where we expect no results. +*/ +static int sql_single_step_statement(fulltext_vtab *v, + fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + int rc = sql_step_statement(v, iStmt, ppStmt); + return (rc==SQLITE_DONE) ? SQLITE_OK : rc; +} + +/* insert into %_content (rowid, content) values ([rowid], [zContent]) */ +static int content_insert(fulltext_vtab *v, sqlite3_value *rowid, + const char *zContent, int nContent){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_value(s, 1, rowid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(s, 2, zContent, nContent, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, CONTENT_INSERT_STMT, &s); +} + +/* select content from %_content where rowid = [iRow] + * The caller must delete the returned string. */ +static int content_select(fulltext_vtab *v, sqlite_int64 iRow, + char **pzContent){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = sql_step_statement(v, CONTENT_SELECT_STMT, &s); + if( rc!=SQLITE_ROW ) return rc; + + *pzContent = string_dup((const char *)sqlite3_column_text(s, 0)); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ) return SQLITE_OK; + + free(*pzContent); + return rc; +} + +/* delete from %_content where rowid = [iRow ] */ +static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iRow); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, CONTENT_DELETE_STMT, &s); +} + +/* select rowid, doclist from %_term where term = [zTerm] and first = [iFirst] + * If found, returns SQLITE_OK; the caller must free the returned doclist. + * If no rows found, returns SQLITE_ERROR. */ +static int term_select(fulltext_vtab *v, const char *zTerm, int nTerm, + sqlite_int64 iFirst, + sqlite_int64 *rowid, + DocList *out){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_TRANSIENT); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iFirst); + if( rc!=SQLITE_OK ) return rc; + + rc = sql_step_statement(v, TERM_SELECT_STMT, &s); + if( rc!=SQLITE_ROW ) return rc==SQLITE_DONE ? SQLITE_ERROR : rc; + + *rowid = sqlite3_column_int64(s, 0); + docListInit(out, DL_POSITIONS_OFFSETS, + sqlite3_column_blob(s, 1), sqlite3_column_bytes(s, 1)); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + return rc==SQLITE_DONE ? SQLITE_OK : rc; +} + +/* select max(first) from %_term where term = [zTerm] and first <= [iFirst] + * If found, returns SQLITE_ROW and result in *piResult; if the query returns + * NULL (meaning no row found) returns SQLITE_DONE. + */ +static int term_chunk_select(fulltext_vtab *v, const char *zTerm, int nTerm, + sqlite_int64 iFirst, sqlite_int64 *piResult){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_CHUNK_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iFirst); + if( rc!=SQLITE_OK ) return rc; + + rc = sql_step_statement(v, TERM_CHUNK_SELECT_STMT, &s); + if( rc!=SQLITE_ROW ) return rc==SQLITE_DONE ? SQLITE_ERROR : rc; + + switch( sqlite3_column_type(s, 0) ){ + case SQLITE_NULL: + rc = SQLITE_DONE; + break; + case SQLITE_INTEGER: + *piResult = sqlite3_column_int64(s, 0); + break; + default: + return SQLITE_ERROR; + } + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + if( sqlite3_step(s) != SQLITE_DONE ) return SQLITE_ERROR; + return rc; +} + +/* insert into %_term (term, first, doclist) + values ([zTerm], [iFirst], [doclist]) */ +static int term_insert(fulltext_vtab *v, const char *zTerm, int nTerm, + sqlite_int64 iFirst, DocList *doclist){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(s, 1, zTerm, nTerm, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iFirst); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 3, doclist->pData, doclist->nData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, TERM_INSERT_STMT, &s); +} + +/* update %_term set doclist = [doclist] where rowid = [rowid] */ +static int term_update(fulltext_vtab *v, sqlite_int64 rowid, + DocList *doclist){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_UPDATE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 1, doclist->pData, doclist->nData, + SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, rowid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, TERM_UPDATE_STMT, &s); +} + +static int term_delete(fulltext_vtab *v, sqlite_int64 rowid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, TERM_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, rowid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step_statement(v, TERM_DELETE_STMT, &s); +} + +static void fulltext_vtab_destroy(fulltext_vtab *v){ + int iStmt; + + for( iStmt=0; iStmtpFulltextStatements[iStmt]!=NULL ){ + sqlite3_finalize(v->pFulltextStatements[iStmt]); + v->pFulltextStatements[iStmt] = NULL; + } + } + + if( v->pTokenizer!=NULL ){ + v->pTokenizer->pModule->xDestroy(v->pTokenizer); + v->pTokenizer = NULL; + } + + free((void *) v->zName); + free(v); +} + +/* Current interface: +** argv[0] - module name +** argv[1] - database name +** argv[2] - table name +** argv[3] - tokenizer name (optional, a sensible default is provided) +** argv[4..] - passed to tokenizer (optional based on tokenizer) +**/ +static int fulltextConnect(sqlite3 *db, void *pAux, int argc, char **argv, + sqlite3_vtab **ppVTab){ + int rc; + fulltext_vtab *v; + sqlite3_tokenizer_module *m = NULL; + + assert( argc>=3 ); + v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab)); + /* sqlite will initialize v->base */ + v->db = db; + v->zName = string_dup(argv[2]); + v->pTokenizer = NULL; + + if( argc==3 ){ + get_simple_tokenizer_module(&m); + } else { + /* TODO(shess) For now, add new tokenizers as else if clauses. */ + if( !strcmp(argv[3], "simple") ){ + get_simple_tokenizer_module(&m); + } else { + assert( "unrecognized tokenizer"==NULL ); + } + } + + /* TODO(shess) Since tokenization impacts the index, the parameters + ** to the tokenizer need to be identical when a persistent virtual + ** table is re-created. One solution would be a meta-table to track + ** such information in the database. Then we could verify that the + ** information is identical on subsequent creates. + */ + /* TODO(shess) Why isn't argv already (const char **)? */ + rc = m->xCreate(argc-3, (const char **) (argv+3), &v->pTokenizer); + if( rc!=SQLITE_OK ) return rc; + v->pTokenizer->pModule = m; + + /* TODO: verify the existence of backing tables foo_content, foo_term */ + + rc = sqlite3_declare_vtab(db, "create table x(content text)"); + if( rc!=SQLITE_OK ) return rc; + + memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); + + *ppVTab = &v->base; + return SQLITE_OK; +} + +static int fulltextCreate(sqlite3 *db, void *pAux, int argc, char **argv, + sqlite3_vtab **ppVTab){ + int rc; + assert( argc>=3 ); + + /* The %_content table holds the text of each full-text item, with + ** the rowid used as the docid. + ** + ** The %_term table maps each term to a document list blob + ** containing elements sorted by ascending docid, each element + ** encoded as: + ** + ** docid varint-encoded + ** token count varint-encoded + ** "count" token elements (poslist): + ** position varint-encoded as delta from previous position + ** start offset varint-encoded as delta from previous start offset + ** end offset varint-encoded as delta from start offset + ** + ** Additionally, doclist blobs can be chunked into multiple rows, + ** using "first" to order the blobs. "first" is simply the first + ** docid in the blob. + */ + /* + ** NOTE(shess) That last sentence is incorrect in the face of + ** deletion, which can leave a doclist that doesn't contain the + ** first from that row. I _believe_ this does not matter to the + ** operation of the system, but it might be reasonable to update + ** appropriately in case this assumption becomes more important. + */ + rc = sql_exec(db, argv[2], + "create table %_content(content text);" + "create table %_term(term text, first integer, doclist blob);" + "create index %_index on %_term(term, first)"); + if( rc!=SQLITE_OK ) return rc; + + return fulltextConnect(db, pAux, argc, argv, ppVTab); +} + +/* Decide how to handle an SQL query. + * At the moment, MATCH queries can include implicit boolean ANDs; we + * haven't implemented phrase searches or OR yet. */ +static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ + int i; + + for(i=0; inConstraint; ++i){ + const struct sqlite3_index_constraint *pConstraint; + pConstraint = &pInfo->aConstraint[i]; + if( pConstraint->iColumn==0 && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH && + pConstraint->usable ){ /* a full-text search */ + pInfo->aConstraintUsage[i].argvIndex = 1; + pInfo->aConstraintUsage[i].omit = 1; + pInfo->idxNum = QUERY_FULLTEXT; + pInfo->estimatedCost = 1.0; /* an arbitrary value for now */ + return SQLITE_OK; + } + } + pInfo->idxNum = QUERY_GENERIC; + return SQLITE_OK; +} + +static int fulltextDisconnect(sqlite3_vtab *pVTab){ + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextDestroy(sqlite3_vtab *pVTab){ + fulltext_vtab *v = (fulltext_vtab *)pVTab; + + int rc = sql_exec(v->db, v->zName, + "drop table %_content; drop table %_term"); + if( rc!=SQLITE_OK ) return rc; + + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + fulltext_cursor *c; + + c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1); + /* sqlite will initialize c->base */ + *ppCursor = &c->base; + + return SQLITE_OK; +} + +static int fulltextClose(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + sqlite3_finalize(c->pStmt); + if( c->result.pDoclist!=NULL ){ + docListDelete(c->result.pDoclist); + } + free(c); + return SQLITE_OK; +} + +static int fulltextNext(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + sqlite_int64 iDocid; + int rc; + + switch( c->iCursorType ){ + case QUERY_GENERIC: + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + switch( rc ){ + case SQLITE_ROW: + c->eof = 0; + return SQLITE_OK; + case SQLITE_DONE: + c->eof = 1; + return SQLITE_OK; + default: + c->eof = 1; + return rc; + } + case QUERY_FULLTEXT: + rc = sqlite3_reset(c->pStmt); + if( rc!=SQLITE_OK ) return rc; + + if( readerAtEnd(&c->result)){ + c->eof = 1; + return SQLITE_OK; + } + iDocid = readDocid(&c->result); + rc = sqlite3_bind_int64(c->pStmt, 1, iDocid); + if( rc!=SQLITE_OK ) return rc; + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + if( rc==SQLITE_ROW ){ /* the case we expect */ + c->eof = 0; + return SQLITE_OK; + } + /* an error occurred; abort */ + return rc==SQLITE_DONE ? SQLITE_ERROR : rc; + default: + assert( 0 ); + return SQLITE_ERROR; /* not reached */ + } +} + +static int term_select_doclist(fulltext_vtab *v, const char *pTerm, int nTerm, + sqlite3_stmt **ppStmt){ + int rc; + if( *ppStmt ){ + rc = sqlite3_reset(*ppStmt); + } else { + rc = sql_prepare(v->db, v->zName, ppStmt, + "select doclist from %_term where term = ? order by first"); + } + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_text(*ppStmt, 1, pTerm, nTerm, SQLITE_TRANSIENT); + if( rc!=SQLITE_OK ) return rc; + + return sqlite3_step(*ppStmt); /* TODO(adamd): handle schema error */ +} + +/* Read the posting list for [zTerm]; AND it with the doclist [in] to + * produce the doclist [out], using the given offset [iOffset] for phrase + * matching. + * (*pSelect) is used to hold an SQLite statement used inside this function; + * the caller should initialize *pSelect to NULL before the first call. + */ +static int query_merge(fulltext_vtab *v, sqlite3_stmt **pSelect, + const char *zTerm, + DocList *pIn, int iOffset, DocList *out){ + int rc; + DocListMerge merge; + + if( pIn!=NULL && !pIn->nData ){ + /* If [pIn] is already empty, there's no point in reading the + * posting list to AND it in; return immediately. */ + return SQLITE_OK; + } + + rc = term_select_doclist(v, zTerm, -1, pSelect); + if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc; + + mergeInit(&merge, pIn, iOffset, out); + while( rc==SQLITE_ROW ){ + DocList block; + docListInit(&block, DL_POSITIONS_OFFSETS, + sqlite3_column_blob(*pSelect, 0), + sqlite3_column_bytes(*pSelect, 0)); + mergeBlock(&merge, &block); + docListDestroy(&block); + + rc = sqlite3_step(*pSelect); + if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ){ + return rc; + } + } + + return SQLITE_OK; +} + +typedef struct QueryTerm { + int is_phrase; /* true if this term begins a new phrase */ + const char *zTerm; +} QueryTerm; + +/* A parsed query. + * + * As an example, parsing the query ["four score" years "new nation"] will + * yield a Query with 5 terms: + * "four", is_phrase = 1 + * "score", is_phrase = 0 + * "years", is_phrase = 1 + * "new", is_phrase = 1 + * "nation", is_phrase = 0 + */ +typedef struct Query { + int nTerms; + QueryTerm *pTerm; +} Query; + +static void query_add(Query *q, int is_phrase, const char *zTerm){ + QueryTerm *t; + ++q->nTerms; + q->pTerm = realloc(q->pTerm, q->nTerms * sizeof(q->pTerm[0])); + t = &q->pTerm[q->nTerms - 1]; + t->is_phrase = is_phrase; + t->zTerm = zTerm; +} + +static void query_free(Query *q){ + int i; + for(i = 0; i < q->nTerms; ++i){ + free((void *) q->pTerm[i].zTerm); + } + free(q->pTerm); +} + +static int tokenize_segment(sqlite3_tokenizer *pTokenizer, + const char *zQuery, int in_phrase, + Query *pQuery){ + sqlite3_tokenizer_module *pModule = pTokenizer->pModule; + sqlite3_tokenizer_cursor *pCursor; + int is_first = 1; + + int rc = pModule->xOpen(pTokenizer, zQuery, -1, &pCursor); + if( rc!=SQLITE_OK ) return rc; + pCursor->pTokenizer = pTokenizer; + + while( 1 ){ + const char *zToken; + int nToken, iStartOffset, iEndOffset, dummy_pos; + + rc = pModule->xNext(pCursor, + &zToken, &nToken, + &iStartOffset, &iEndOffset, + &dummy_pos); + if( rc!=SQLITE_OK ) break; + query_add(pQuery, !in_phrase || is_first, string_dup_n(zToken, nToken)); + is_first = 0; + } + + return pModule->xClose(pCursor); +} + +/* Parse a query string, yielding a Query object. */ +static int parse_query(fulltext_vtab *v, const char *zQuery, Query *pQuery){ + char *zQuery1 = string_dup(zQuery); + int in_phrase = 0; + char *s = zQuery1; + pQuery->nTerms = 0; + pQuery->pTerm = NULL; + + while( *s ){ + char *t = s; + while( *t ){ + if( *t=='"' ){ + *t++ = '\0'; + break; + } + ++t; + } + if( *s ){ + tokenize_segment(v->pTokenizer, s, in_phrase, pQuery); + } + s = t; + in_phrase = !in_phrase; + } + + free(zQuery1); + return SQLITE_OK; +} + +/* Perform a full-text query; return a list of documents in [pResult]. */ +static int fulltext_query(fulltext_vtab *v, const char *zQuery, + DocList **pResult){ + Query q; + int phrase_start = -1; + int i; + sqlite3_stmt *pSelect = NULL; + DocList *d = NULL; + + int rc = parse_query(v, zQuery, &q); + if( rc!=SQLITE_OK ) return rc; + + /* Merge terms. */ + for(i = 0 ; i < q.nTerms ; ++i){ + /* In each merge step, we need to generate positions whenever we're + * processing a phrase which hasn't ended yet. */ + int need_positions = iiCursorType = idxNum; + switch( idxNum ){ + case QUERY_GENERIC: + zStatement = "select rowid, content from %_content"; + break; + + case QUERY_FULLTEXT: /* full-text search */ + { + const char *zQuery = (const char *)sqlite3_value_text(argv[0]); + DocList *pResult; + assert( argc==1 ); + rc = fulltext_query(v, zQuery, &pResult); + if( rc!=SQLITE_OK ) return rc; + readerInit(&c->result, pResult); + zStatement = "select rowid, content from %_content where rowid = ?"; + break; + } + + default: + assert( 0 ); + } + + rc = sql_prepare(v->db, v->zName, &c->pStmt, zStatement); + if( rc!=SQLITE_OK ) return rc; + + return fulltextNext(pCursor); +} + +static int fulltextEof(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + return c->eof; +} + +static int fulltextColumn(sqlite3_vtab_cursor *pCursor, + sqlite3_context *pContext, int idxCol){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + const char *s; + + assert( idxCol==0 ); + s = (const char *) sqlite3_column_text(c->pStmt, 1); + sqlite3_result_text(pContext, s, -1, SQLITE_TRANSIENT); + + return SQLITE_OK; +} + +static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + + *pRowid = sqlite3_column_int64(c->pStmt, 0); + return SQLITE_OK; +} + +/* Build a hash table containing all terms in zText. */ +static int build_terms(Hash *terms, sqlite3_tokenizer *pTokenizer, + const char *zText, sqlite_int64 iDocid){ + sqlite3_tokenizer_cursor *pCursor; + const char *pToken; + int nTokenBytes; + int iStartOffset, iEndOffset, iPosition; + + int rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor); + if( rc!=SQLITE_OK ) return rc; + + pCursor->pTokenizer = pTokenizer; + HashInit(terms, HASH_STRING, 1); + while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor, + &pToken, &nTokenBytes, + &iStartOffset, &iEndOffset, + &iPosition) ){ + DocList *p; + + /* Positions can't be negative; we use -1 as a terminator internally. */ + if( iPosition<0 ) { + rc = SQLITE_ERROR; + goto err; + } + + p = HashFind(terms, pToken, nTokenBytes); + if( p==NULL ){ + p = docListNew(DL_POSITIONS_OFFSETS); + docListAddDocid(p, iDocid); + HashInsert(terms, pToken, nTokenBytes, p); + } + docListAddPosOffset(p, iPosition, iStartOffset, iEndOffset); + } + +err: + /* TODO(shess) Check return? Should this be able to cause errors at + ** this point? Actually, same question about sqlite3_finalize(), + ** though one could argue that failure there means that the data is + ** not durable. *ponder* + */ + pTokenizer->pModule->xClose(pCursor); + return rc; +} +/* Update the %_terms table to map the term [zTerm] to the given rowid. */ +static int index_insert_term(fulltext_vtab *v, const char *zTerm, int nTerm, + sqlite_int64 iDocid, DocList *p){ + sqlite_int64 iFirst; + sqlite_int64 iIndexRow; + DocList doclist; + + int rc = term_chunk_select(v, zTerm, nTerm, iDocid, &iFirst); + if( rc==SQLITE_DONE ){ + docListInit(&doclist, DL_POSITIONS_OFFSETS, 0, 0); + if( docListUpdate(&doclist, iDocid, p) ){ + rc = term_insert(v, zTerm, nTerm, iDocid, &doclist); + docListDestroy(&doclist); + return rc; + } + return SQLITE_OK; + } + if( rc!=SQLITE_ROW ) return SQLITE_ERROR; + + /* This word is in the index; add this document ID to its blob. */ + + rc = term_select(v, zTerm, nTerm, iFirst, &iIndexRow, &doclist); + if( rc!=SQLITE_OK ) return rc; + + if( docListUpdate(&doclist, iDocid, p) ){ + /* If the blob is too big, split it in half. */ + if( doclist.nData>CHUNK_MAX ){ + DocList half; + if( docListSplit(&doclist, &half) ){ + rc = term_insert(v, zTerm, nTerm, firstDocid(&half), &half); + docListDestroy(&half); + if( rc!=SQLITE_OK ) goto err; + } + } + rc = term_update(v, iIndexRow, &doclist); + } + +err: + docListDestroy(&doclist); + return rc; +} + +/* Insert a row into the full-text index; set *piRowid to be the ID of the + * new row. */ +static int index_insert(fulltext_vtab *v, + sqlite3_value *pRequestRowid, const char *zText, + sqlite_int64 *piRowid){ + Hash terms; /* maps term string -> PosList */ + HashElem *e; + + int rc = content_insert(v, pRequestRowid, zText, -1); + if( rc!=SQLITE_OK ) return rc; + *piRowid = sqlite3_last_insert_rowid(v->db); + + if( !zText ) return SQLITE_OK; /* nothing to index */ + + rc = build_terms(&terms, v->pTokenizer, zText, *piRowid); + if( rc!=SQLITE_OK ) return rc; + + for(e=HashFirst(&terms); e; e=HashNext(e)){ + DocList *p = HashData(e); + rc = index_insert_term(v, HashKey(e), HashKeysize(e), *piRowid, p); + if( rc!=SQLITE_OK ) break; + } + + for(e=HashFirst(&terms); e; e=HashNext(e)){ + DocList *p = HashData(e); + docListDelete(p); + } + HashClear(&terms); + return rc; +} + +static int index_delete_term(fulltext_vtab *v, const char *zTerm, int nTerm, + sqlite_int64 iDocid){ + sqlite_int64 iFirst; + sqlite_int64 iIndexRow; + DocList doclist; + + int rc = term_chunk_select(v, zTerm, nTerm, iDocid, &iFirst); + if( rc!=SQLITE_ROW ) return SQLITE_ERROR; + + rc = term_select(v, zTerm, nTerm, iFirst, &iIndexRow, &doclist); + if( rc!=SQLITE_OK ) return rc; + + if( docListUpdate(&doclist, iDocid, NULL) ){ + if( doclist.nData>0 ){ + rc = term_update(v, iIndexRow, &doclist); + } else { /* empty posting list */ + rc = term_delete(v, iIndexRow); + } + } + docListDestroy(&doclist); + return rc; +} + +/* Delete a row from the full-text index. */ +static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ + char *zText; + Hash terms; + HashElem *e; + + int rc = content_select(v, iRow, &zText); + if( rc!=SQLITE_OK ) return rc; + + rc = build_terms(&terms, v->pTokenizer, zText, iRow); + free(zText); + if( rc!=SQLITE_OK ) return rc; + + for(e=HashFirst(&terms); e; e=HashNext(e)){ + rc = index_delete_term(v, HashKey(e), HashKeysize(e), iRow); + if( rc!=SQLITE_OK ) break; + } + for(e=HashFirst(&terms); e; e=HashNext(e)){ + DocList *p = HashData(e); + docListDelete(p); + } + HashClear(&terms); + + return content_delete(v, iRow); +} + +static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, + sqlite_int64 *pRowid){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + + if( nArg<2 ){ + return index_delete(v, sqlite3_value_int64(ppArg[0])); + } + + if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){ + return SQLITE_ERROR; /* an update; not yet supported */ + } + + assert( nArg==3 ); /* ppArg[1] = rowid, ppArg[2] = content */ + return index_insert(v, ppArg[1], + (const char *)sqlite3_value_text(ppArg[2]), pRowid); +} + +static sqlite3_module fulltextModule = { + 0, + fulltextCreate, + fulltextConnect, + fulltextBestIndex, + fulltextDisconnect, + fulltextDestroy, + fulltextOpen, + fulltextClose, + fulltextFilter, + fulltextNext, + fulltextEof, + fulltextColumn, + fulltextRowid, + fulltextUpdate +}; + +int fulltext_init(sqlite3 *db){ + return sqlite3_create_module(db, "fulltext", &fulltextModule, 0); +} + +#if !SQLITE_CORE +int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, + const sqlite3_api_routines *pApi){ + SQLITE_EXTENSION_INIT2(pApi) + return fulltext_init(db); +} +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.h new file mode 100644 index 0000000..477dcab --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/fulltext.h @@ -0,0 +1,11 @@ +#include "sqlite3.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int fulltext_init(sqlite3 *db); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/simple_tokenizer.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/simple_tokenizer.c new file mode 100644 index 0000000..d00a770 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/simple_tokenizer.c @@ -0,0 +1,174 @@ +/* +** The author disclaims copyright to this source code. +** +************************************************************************* +** Implementation of the "simple" full-text-search tokenizer. +*/ + +#include +#if !defined(__APPLE__) +#include +#else +#include +#endif +#include +#include +#include + +#include "tokenizer.h" + +/* Duplicate a string; the caller must free() the returned string. + * (We don't use strdup() since it's not part of the standard C library and + * may not be available everywhere.) */ +/* TODO(shess) Copied from fulltext.c, consider util.c for such +** things. */ +static char *string_dup(const char *s){ + char *str = malloc(strlen(s) + 1); + strcpy(str, s); + return str; +} + +typedef struct simple_tokenizer { + sqlite3_tokenizer base; + const char *zDelim; /* token delimiters */ +} simple_tokenizer; + +typedef struct simple_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *pInput; /* input we are tokenizing */ + int nBytes; /* size of the input */ + const char *pCurrent; /* current position in pInput */ + int iToken; /* index of next token to be returned */ + char *zToken; /* storage for current token */ + int nTokenBytes; /* actual size of current token */ + int nTokenAllocated; /* space allocated to zToken buffer */ +} simple_tokenizer_cursor; + +static sqlite3_tokenizer_module simpleTokenizerModule;/* forward declaration */ + +static int simpleCreate( + int argc, const char **argv, + sqlite3_tokenizer **ppTokenizer +){ + simple_tokenizer *t; + + t = (simple_tokenizer *) malloc(sizeof(simple_tokenizer)); + /* TODO(shess) Delimiters need to remain the same from run to run, + ** else we need to reindex. One solution would be a meta-table to + ** track such information in the database, then we'd only want this + ** information on the initial create. + */ + if( argc>1 ){ + t->zDelim = string_dup(argv[1]); + } else { + /* Build a string excluding alphanumeric ASCII characters */ + char zDelim[0x80]; /* nul-terminated, so nul not a member */ + int i, j; + for(i=1, j=0; i<0x80; i++){ + if( !isalnum(i) ){ + zDelim[j++] = i; + } + } + zDelim[j++] = '\0'; + assert( j<=sizeof(zDelim) ); + t->zDelim = string_dup(zDelim); + } + + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ + simple_tokenizer *t = (simple_tokenizer *) pTokenizer; + + free((void *) t->zDelim); + free(t); + + return SQLITE_OK; +} + +static int simpleOpen( + sqlite3_tokenizer *pTokenizer, + const char *pInput, int nBytes, + sqlite3_tokenizer_cursor **ppCursor +){ + simple_tokenizer_cursor *c; + + c = (simple_tokenizer_cursor *) malloc(sizeof(simple_tokenizer_cursor)); + c->pInput = pInput; + c->nBytes = nBytes<0 ? (int) strlen(pInput) : nBytes; + c->pCurrent = c->pInput; /* start tokenizing at the beginning */ + c->iToken = 0; + c->zToken = NULL; /* no space allocated, yet. */ + c->nTokenBytes = 0; + c->nTokenAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + + if( NULL!=c->zToken ){ + free(c->zToken); + } + free(c); + + return SQLITE_OK; +} + +static int simpleNext( + sqlite3_tokenizer_cursor *pCursor, + const char **ppToken, int *pnBytes, + int *piStartOffset, int *piEndOffset, int *piPosition +){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; + int ii; + + while( c->pCurrent-c->pInputnBytes ){ + int n = (int) strcspn(c->pCurrent, t->zDelim); + if( n>0 ){ + if( n+1>c->nTokenAllocated ){ + c->zToken = realloc(c->zToken, n+1); + } + for(ii=0; iipCurrent[ii]; + c->zToken[ii] = (unsigned char)ch<0x80 ? tolower(ch) : ch; + } + c->zToken[n] = '\0'; + *ppToken = c->zToken; + *pnBytes = n; + *piStartOffset = (int) (c->pCurrent-c->pInput); + *piEndOffset = *piStartOffset+n; + *piPosition = c->iToken++; + c->pCurrent += n + 1; + + return SQLITE_OK; + } + c->pCurrent += n + 1; + /* TODO(shess) could strspn() to skip delimiters en masse. Needs + ** to happen in two places, though, which is annoying. + */ + } + return SQLITE_DONE; +} + +static sqlite3_tokenizer_module simpleTokenizerModule = { + 0, + simpleCreate, + simpleDestroy, + simpleOpen, + simpleClose, + simpleNext, +}; + +void get_simple_tokenizer_module( + sqlite3_tokenizer_module **ppModule +){ + *ppModule = &simpleTokenizerModule; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts1/tokenizer.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/tokenizer.h new file mode 100644 index 0000000..1d7bd1f --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts1/tokenizer.h @@ -0,0 +1,89 @@ +/* +** 2006 July 10 +** +** The author disclaims copyright to this source code. +** +************************************************************************* +** Defines the interface to tokenizers used by fulltext-search. There +** are three basic components: +** +** sqlite3_tokenizer_module is a singleton defining the tokenizer +** interface functions. This is essentially the class structure for +** tokenizers. +** +** sqlite3_tokenizer is used to define a particular tokenizer, perhaps +** including customization information defined at creation time. +** +** sqlite3_tokenizer_cursor is generated by a tokenizer to generate +** tokens from a particular input. +*/ +#ifndef _TOKENIZER_H_ +#define _TOKENIZER_H_ + +/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. +** If tokenizers are to be allowed to call sqlite3_*() functions, then +** we will need a way to register the API consistently. +*/ +#include "sqlite3.h" + +/* +** Structures used by the tokenizer interface. +*/ +typedef struct sqlite3_tokenizer sqlite3_tokenizer; +typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; +typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; + +struct sqlite3_tokenizer_module { + int iVersion; /* currently 0 */ + + /* + ** Create and destroy a tokenizer. argc/argv are passed down from + ** the fulltext virtual table creation to allow customization. + */ + int (*xCreate)(int argc, const char **argv, + sqlite3_tokenizer **ppTokenizer); + int (*xDestroy)(sqlite3_tokenizer *pTokenizer); + + /* + ** Tokenize a particular input. Call xOpen() to prepare to + ** tokenize, xNext() repeatedly until it returns SQLITE_DONE, then + ** xClose() to free any internal state. The pInput passed to + ** xOpen() must exist until the cursor is closed. The ppToken + ** result from xNext() is only valid until the next call to xNext() + ** or until xClose() is called. + */ + /* TODO(shess) current implementation requires pInput to be + ** nul-terminated. This should either be fixed, or pInput/nBytes + ** should be converted to zInput. + */ + int (*xOpen)(sqlite3_tokenizer *pTokenizer, + const char *pInput, int nBytes, + sqlite3_tokenizer_cursor **ppCursor); + int (*xClose)(sqlite3_tokenizer_cursor *pCursor); + int (*xNext)(sqlite3_tokenizer_cursor *pCursor, + const char **ppToken, int *pnBytes, + int *piStartOffset, int *piEndOffset, int *piPosition); +}; + +struct sqlite3_tokenizer { + sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ + /* Tokenizer implementations will typically add additional fields */ +}; + +struct sqlite3_tokenizer_cursor { + sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ + /* Tokenizer implementations will typically add additional fields */ +}; + +/* +** Get the module for a tokenizer which generates tokens based on a +** set of non-token characters. The default is to break tokens at any +** non-alnum character, though the set of delimiters can also be +** specified by the first argv argument to xCreate(). +*/ +/* TODO(shess) This doesn't belong here. Need some sort of +** registration process. +*/ +void get_simple_tokenizer_module(sqlite3_tokenizer_module **ppModule); + +#endif /* _TOKENIZER_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Entries b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Entries new file mode 100644 index 0000000..05243d8 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Entries @@ -0,0 +1,13 @@ +/README.txt/1.1/Tue Oct 10 17:37:14 2006// +/fts2.h/1.3/Fri Nov 30 01:28:10 2007// +/fts2_hash.c/1.2/Fri Nov 30 01:28:10 2007// +/fts2_hash.h/1.1/Tue Oct 10 17:37:14 2006// +/fts2_icu.c/1.1/Fri Jun 22 15:21:16 2007// +/fts2_porter.c/1.7/Fri Nov 30 01:28:10 2007// +/fts2_tokenizer.c/1.6/Tue Jun 26 10:55:02 2007// +/fts2_tokenizer.h/1.3/Fri Nov 30 01:28:10 2007// +/fts2_tokenizer1.c/1.5/Fri Nov 30 01:28:10 2007// +/mkfts2amal.tcl/1.3/Fri Nov 30 01:28:10 2007// +/README.tokenizers/1.3/Thu Dec 13 21:44:03 2007// +/fts2.c/1.48/Thu Dec 13 21:45:31 2007// +D diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Repository b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Repository new file mode 100644 index 0000000..f52cff4 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Repository @@ -0,0 +1 @@ +sqlite/ext/fts2 diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Root b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Root new file mode 100644 index 0000000..a3ae5d0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/CVS/Root @@ -0,0 +1 @@ +:pserver:drh@sqlite.org:/sqlite diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.tokenizers b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.tokenizers new file mode 100644 index 0000000..98d2021 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.tokenizers @@ -0,0 +1,133 @@ + +1. FTS2 Tokenizers + + When creating a new full-text table, FTS2 allows the user to select + the text tokenizer implementation to be used when indexing text + by specifying a "tokenizer" clause as part of the CREATE VIRTUAL TABLE + statement: + + CREATE VIRTUAL TABLE USING fts2( + [, tokenizer []] + ); + + The built-in tokenizers (valid values to pass as ) are + "simple" and "porter". + + should consist of zero or more white-space separated + arguments to pass to the selected tokenizer implementation. The + interpretation of the arguments, if any, depends on the individual + tokenizer. + +2. Custom Tokenizers + + FTS2 allows users to provide custom tokenizer implementations. The + interface used to create a new tokenizer is defined and described in + the fts2_tokenizer.h source file. + + Registering a new FTS2 tokenizer is similar to registering a new + virtual table module with SQLite. The user passes a pointer to a + structure containing pointers to various callback functions that + make up the implementation of the new tokenizer type. For tokenizers, + the structure (defined in fts2_tokenizer.h) is called + "sqlite3_tokenizer_module". + + FTS2 does not expose a C-function that users call to register new + tokenizer types with a database handle. Instead, the pointer must + be encoded as an SQL blob value and passed to FTS2 through the SQL + engine by evaluating a special scalar function, "fts2_tokenizer()". + The fts2_tokenizer() function may be called with one or two arguments, + as follows: + + SELECT fts2_tokenizer(); + SELECT fts2_tokenizer(, ); + + Where is a string identifying the tokenizer and + is a pointer to an sqlite3_tokenizer_module + structure encoded as an SQL blob. If the second argument is present, + it is registered as tokenizer and a copy of it + returned. If only one argument is passed, a pointer to the tokenizer + implementation currently registered as is returned, + encoded as a blob. Or, if no such tokenizer exists, an SQL exception + (error) is raised. + + SECURITY: If the fts2 extension is used in an environment where potentially + malicious users may execute arbitrary SQL (i.e. gears), they should be + prevented from invoking the fts2_tokenizer() function, possibly using the + authorisation callback. + + See "Sample code" below for an example of calling the fts2_tokenizer() + function from C code. + +3. ICU Library Tokenizers + + If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor + symbol defined, then there exists a built-in tokenizer named "icu" + implemented using the ICU library. The first argument passed to the + xCreate() method (see fts2_tokenizer.h) of this tokenizer may be + an ICU locale identifier. For example "tr_TR" for Turkish as used + in Turkey, or "en_AU" for English as used in Australia. For example: + + "CREATE VIRTUAL TABLE thai_text USING fts2(text, tokenizer icu th_TH)" + + The ICU tokenizer implementation is very simple. It splits the input + text according to the ICU rules for finding word boundaries and discards + any tokens that consist entirely of white-space. This may be suitable + for some applications in some locales, but not all. If more complex + processing is required, for example to implement stemming or + discard punctuation, this can be done by creating a tokenizer + implementation that uses the ICU tokenizer as part of its implementation. + + When using the ICU tokenizer this way, it is safe to overwrite the + contents of the strings returned by the xNext() method (see + fts2_tokenizer.h). + +4. Sample code. + + The following two code samples illustrate the way C code should invoke + the fts2_tokenizer() scalar function: + + int registerTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module *p + ){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts2_tokenizer(?, ?)"; + + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); + sqlite3_step(pStmt); + + return sqlite3_finalize(pStmt); + } + + int queryTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module **pp + ){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts2_tokenizer(?)"; + + *pp = 0; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ + memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); + } + } + + return sqlite3_finalize(pStmt); + } diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.txt b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.txt new file mode 100644 index 0000000..517a2a0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/README.txt @@ -0,0 +1,4 @@ +This folder contains source code to the second full-text search +extension for SQLite. While the API is the same, this version uses a +substantially different storage schema from fts1, so tables will need +to be rebuilt. diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.c new file mode 100644 index 0000000..1c0c02e --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.c @@ -0,0 +1,5937 @@ +/* fts2 has a design flaw which can lead to database corruption (see +** below). It is recommended not to use it any longer, instead use +** fts3 (or higher). If you believe that your use of fts2 is safe, +** add -DSQLITE_ENABLE_BROKEN_FTS2=1 to your CFLAGS. +*/ +#if (!defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2)) \ + && !defined(SQLITE_ENABLE_BROKEN_FTS2) +#error fts2 has a design flaw and has been deprecated. +#endif +/* The flaw is that fts2 uses the content table's unaliased rowid as +** the unique docid. fts2 embeds the rowid in the index it builds, +** and expects the rowid to not change. The SQLite VACUUM operation +** will renumber such rowids, thereby breaking fts2. If you are using +** fts2 in a system which has disabled VACUUM, then you can continue +** to use it safely. Note that PRAGMA auto_vacuum does NOT disable +** VACUUM, though systems using auto_vacuum are unlikely to invoke +** VACUUM. +** +** Unlike fts1, which is safe across VACUUM if you never delete +** documents, fts2 has a second exposure to this flaw, in the segments +** table. So fts2 should be considered unsafe across VACUUM in all +** cases. +*/ + +/* +** 2006 Oct 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. +** +****************************************************************************** +** +** This is an SQLite module implementing full-text search. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS2 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS2 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). +*/ + +/* TODO(shess) Consider exporting this comment to an HTML file or the +** wiki. +*/ +/* The full-text index is stored in a series of b+tree (-like) +** structures called segments which map terms to doclists. The +** structures are like b+trees in layout, but are constructed from the +** bottom up in optimal fashion and are not updatable. Since trees +** are built from the bottom up, things will be described from the +** bottom up. +** +** +**** Varints **** +** The basic unit of encoding is a variable-length integer called a +** varint. We encode variable-length integers in little-endian order +** using seven bits * per byte as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** and so on. +** +** This is identical to how sqlite encodes varints (see util.c). +** +** +**** Document lists **** +** A doclist (document list) holds a docid-sorted list of hits for a +** given term. Doclists hold docids, and can optionally associate +** token positions and offsets with docids. +** +** A DL_POSITIONS_OFFSETS doclist is stored like this: +** +** array { +** varint docid; +** array { (position list for column 0) +** varint position; (delta from previous position plus POS_BASE) +** varint startOffset; (delta from previous startOffset) +** varint endOffset; (delta from startOffset) +** } +** array { +** varint POS_COLUMN; (marks start of position list for new column) +** varint column; (index of new column) +** array { +** varint position; (delta from previous position plus POS_BASE) +** varint startOffset;(delta from previous startOffset) +** varint endOffset; (delta from startOffset) +** } +** } +** varint POS_END; (marks end of positions for this document. +** } +** +** Here, array { X } means zero or more occurrences of X, adjacent in +** memory. A "position" is an index of a token in the token stream +** generated by the tokenizer, while an "offset" is a byte offset, +** both based at 0. Note that POS_END and POS_COLUMN occur in the +** same logical place as the position element, and act as sentinals +** ending a position list array. +** +** A DL_POSITIONS doclist omits the startOffset and endOffset +** information. A DL_DOCIDS doclist omits both the position and +** offset information, becoming an array of varint-encoded docids. +** +** On-disk data is stored as type DL_DEFAULT, so we don't serialize +** the type. Due to how deletion is implemented in the segmentation +** system, on-disk doclists MUST store at least positions. +** +** +**** Segment leaf nodes **** +** Segment leaf nodes store terms and doclists, ordered by term. Leaf +** nodes are written using LeafWriter, and read using LeafReader (to +** iterate through a single leaf node's data) and LeavesReader (to +** iterate through a segment's entire leaf layer). Leaf nodes have +** the format: +** +** varint iHeight; (height from leaf level, always 0) +** varint nTerm; (length of first term) +** char pTerm[nTerm]; (content of first term) +** varint nDoclist; (length of term's associated doclist) +** char pDoclist[nDoclist]; (content of doclist) +** array { +** (further terms are delta-encoded) +** varint nPrefix; (length of prefix shared with previous term) +** varint nSuffix; (length of unshared suffix) +** char pTermSuffix[nSuffix];(unshared suffix of next term) +** varint nDoclist; (length of term's associated doclist) +** char pDoclist[nDoclist]; (content of doclist) +** } +** +** Here, array { X } means zero or more occurrences of X, adjacent in +** memory. +** +** Leaf nodes are broken into blocks which are stored contiguously in +** the %_segments table in sorted order. This means that when the end +** of a node is reached, the next term is in the node with the next +** greater node id. +** +** New data is spilled to a new leaf node when the current node +** exceeds LEAF_MAX bytes (default 2048). New data which itself is +** larger than STANDALONE_MIN (default 1024) is placed in a standalone +** node (a leaf node with a single term and doclist). The goal of +** these settings is to pack together groups of small doclists while +** making it efficient to directly access large doclists. The +** assumption is that large doclists represent terms which are more +** likely to be query targets. +** +** TODO(shess) It may be useful for blocking decisions to be more +** dynamic. For instance, it may make more sense to have a 2.5k leaf +** node rather than splitting into 2k and .5k nodes. My intuition is +** that this might extend through 2x or 4x the pagesize. +** +** +**** Segment interior nodes **** +** Segment interior nodes store blockids for subtree nodes and terms +** to describe what data is stored by the each subtree. Interior +** nodes are written using InteriorWriter, and read using +** InteriorReader. InteriorWriters are created as needed when +** SegmentWriter creates new leaf nodes, or when an interior node +** itself grows too big and must be split. The format of interior +** nodes: +** +** varint iHeight; (height from leaf level, always >0) +** varint iBlockid; (block id of node's leftmost subtree) +** optional { +** varint nTerm; (length of first term) +** char pTerm[nTerm]; (content of first term) +** array { +** (further terms are delta-encoded) +** varint nPrefix; (length of shared prefix with previous term) +** varint nSuffix; (length of unshared suffix) +** char pTermSuffix[nSuffix]; (unshared suffix of next term) +** } +** } +** +** Here, optional { X } means an optional element, while array { X } +** means zero or more occurrences of X, adjacent in memory. +** +** An interior node encodes n terms separating n+1 subtrees. The +** subtree blocks are contiguous, so only the first subtree's blockid +** is encoded. The subtree at iBlockid will contain all terms less +** than the first term encoded (or all terms if no term is encoded). +** Otherwise, for terms greater than or equal to pTerm[i] but less +** than pTerm[i+1], the subtree for that term will be rooted at +** iBlockid+i. Interior nodes only store enough term data to +** distinguish adjacent children (if the rightmost term of the left +** child is "something", and the leftmost term of the right child is +** "wicked", only "w" is stored). +** +** New data is spilled to a new interior node at the same height when +** the current node exceeds INTERIOR_MAX bytes (default 2048). +** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing +** interior nodes and making the tree too skinny. The interior nodes +** at a given height are naturally tracked by interior nodes at +** height+1, and so on. +** +** +**** Segment directory **** +** The segment directory in table %_segdir stores meta-information for +** merging and deleting segments, and also the root node of the +** segment's tree. +** +** The root node is the top node of the segment's tree after encoding +** the entire segment, restricted to ROOT_MAX bytes (default 1024). +** This could be either a leaf node or an interior node. If the top +** node requires more than ROOT_MAX bytes, it is flushed to %_segments +** and a new root interior node is generated (which should always fit +** within ROOT_MAX because it only needs space for 2 varints, the +** height and the blockid of the previous root). +** +** The meta-information in the segment directory is: +** level - segment level (see below) +** idx - index within level +** - (level,idx uniquely identify a segment) +** start_block - first leaf node +** leaves_end_block - last leaf node +** end_block - last block (including interior nodes) +** root - contents of root node +** +** If the root node is a leaf node, then start_block, +** leaves_end_block, and end_block are all 0. +** +** +**** Segment merging **** +** To amortize update costs, segments are groups into levels and +** merged in matches. Each increase in level represents exponentially +** more documents. +** +** New documents (actually, document updates) are tokenized and +** written individually (using LeafWriter) to a level 0 segment, with +** incrementing idx. When idx reaches MERGE_COUNT (default 16), all +** level 0 segments are merged into a single level 1 segment. Level 1 +** is populated like level 0, and eventually MERGE_COUNT level 1 +** segments are merged to a single level 2 segment (representing +** MERGE_COUNT^2 updates), and so on. +** +** A segment merge traverses all segments at a given level in +** parallel, performing a straightforward sorted merge. Since segment +** leaf nodes are written in to the %_segments table in order, this +** merge traverses the underlying sqlite disk structures efficiently. +** After the merge, all segment blocks from the merged level are +** deleted. +** +** MERGE_COUNT controls how often we merge segments. 16 seems to be +** somewhat of a sweet spot for insertion performance. 32 and 64 show +** very similar performance numbers to 16 on insertion, though they're +** a tiny bit slower (perhaps due to more overhead in merge-time +** sorting). 8 is about 20% slower than 16, 4 about 50% slower than +** 16, 2 about 66% slower than 16. +** +** At query time, high MERGE_COUNT increases the number of segments +** which need to be scanned and merged. For instance, with 100k docs +** inserted: +** +** MERGE_COUNT segments +** 16 25 +** 8 12 +** 4 10 +** 2 6 +** +** This appears to have only a moderate impact on queries for very +** frequent terms (which are somewhat dominated by segment merge +** costs), and infrequent and non-existent terms still seem to be fast +** even with many segments. +** +** TODO(shess) That said, it would be nice to have a better query-side +** argument for MERGE_COUNT of 16. Also, it is possible/likely that +** optimizations to things like doclist merging will swing the sweet +** spot around. +** +** +** +**** Handling of deletions and updates **** +** Since we're using a segmented structure, with no docid-oriented +** index into the term index, we clearly cannot simply update the term +** index when a document is deleted or updated. For deletions, we +** write an empty doclist (varint(docid) varint(POS_END)), for updates +** we simply write the new doclist. Segment merges overwrite older +** data for a particular docid with newer data, so deletes or updates +** will eventually overtake the earlier data and knock it out. The +** query logic likewise merges doclists so that newer data knocks out +** older data. +** +** TODO(shess) Provide a VACUUM type operation to clear out all +** deletions and duplications. This would basically be a forced merge +** into a single segment. +*/ + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) + +#if defined(SQLITE_ENABLE_FTS2) && !defined(SQLITE_CORE) +# define SQLITE_CORE 1 +#endif + +#include +#include +#include +#include +#include + +#include "fts2.h" +#include "fts2_hash.h" +#include "fts2_tokenizer.h" +#include "sqlite3.h" +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + + +/* TODO(shess) MAN, this thing needs some refactoring. At minimum, it +** would be nice to order the file better, perhaps something along the +** lines of: +** +** - utility functions +** - table setup functions +** - table update functions +** - table query functions +** +** Put the query functions last because they're likely to reference +** typedefs or functions from the table update section. +*/ + +#if 0 +# define TRACE(A) printf A; fflush(stdout) +#else +# define TRACE(A) +#endif + +/* It is not safe to call isspace(), tolower(), or isalnum() on +** hi-bit-set characters. This is the same solution used in the +** tokenizer. +*/ +/* TODO(shess) The snippet-generation code should be using the +** tokenizer-generated tokens rather than doing its own local +** tokenization. +*/ +/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ +static int safe_isspace(char c){ + return (c&0x80)==0 ? isspace(c) : 0; +} +static int safe_tolower(char c){ + return (c&0x80)==0 ? tolower(c) : c; +} +static int safe_isalnum(char c){ + return (c&0x80)==0 ? isalnum(c) : 0; +} + +typedef enum DocListType { + DL_DOCIDS, /* docids only */ + DL_POSITIONS, /* docids + positions */ + DL_POSITIONS_OFFSETS /* docids + positions + offsets */ +} DocListType; + +/* +** By default, only positions and not offsets are stored in the doclists. +** To change this so that offsets are stored too, compile with +** +** -DDL_DEFAULT=DL_POSITIONS_OFFSETS +** +** If DL_DEFAULT is set to DL_DOCIDS, your table can only be inserted +** into (no deletes or updates). +*/ +#ifndef DL_DEFAULT +# define DL_DEFAULT DL_POSITIONS +#endif + +enum { + POS_END = 0, /* end of this position list */ + POS_COLUMN, /* followed by new column number */ + POS_BASE +}; + +/* MERGE_COUNT controls how often we merge segments (see comment at +** top of file). +*/ +#define MERGE_COUNT 16 + +/* utility functions */ + +/* CLEAR() and SCRAMBLE() abstract memset() on a pointer to a single +** record to prevent errors of the form: +** +** my_function(SomeType *b){ +** memset(b, '\0', sizeof(b)); // sizeof(b)!=sizeof(*b) +** } +*/ +/* TODO(shess) Obvious candidates for a header file. */ +#define CLEAR(b) memset(b, '\0', sizeof(*(b))) + +#ifndef NDEBUG +# define SCRAMBLE(b) memset(b, 0x55, sizeof(*(b))) +#else +# define SCRAMBLE(b) +#endif + +/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */ +#define VARINT_MAX 10 + +/* Write a 64-bit variable-length integer to memory starting at p[0]. + * The length of data written will be between 1 and VARINT_MAX bytes. + * The number of bytes written is returned. */ +static int putVarint(char *p, sqlite_int64 v){ + unsigned char *q = (unsigned char *) p; + sqlite_uint64 vu = v; + do{ + *q++ = (unsigned char) ((vu & 0x7f) | 0x80); + vu >>= 7; + }while( vu!=0 ); + q[-1] &= 0x7f; /* turn off high bit in final byte */ + assert( q - (unsigned char *)p <= VARINT_MAX ); + return (int) (q - (unsigned char *)p); +} + +/* Read a 64-bit variable-length integer from memory starting at p[0]. + * Return the number of bytes read, or 0 on error. + * The value is stored in *v. */ +static int getVarint(const char *p, sqlite_int64 *v){ + const unsigned char *q = (const unsigned char *) p; + sqlite_uint64 x = 0, y = 1; + while( (*q & 0x80) == 0x80 ){ + x += y * (*q++ & 0x7f); + y <<= 7; + if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */ + assert( 0 ); + return 0; + } + } + x += y * (*q++); + *v = (sqlite_int64) x; + return (int) (q - (unsigned char *)p); +} + +static int getVarint32(const char *p, int *pi){ + sqlite_int64 i; + int ret = getVarint(p, &i); + *pi = (int) i; + assert( *pi==i ); + return ret; +} + +/*******************************************************************/ +/* DataBuffer is used to collect data into a buffer in piecemeal +** fashion. It implements the usual distinction between amount of +** data currently stored (nData) and buffer capacity (nCapacity). +** +** dataBufferInit - create a buffer with given initial capacity. +** dataBufferReset - forget buffer's data, retaining capacity. +** dataBufferDestroy - free buffer's data. +** dataBufferExpand - expand capacity without adding data. +** dataBufferAppend - append data. +** dataBufferAppend2 - append two pieces of data at once. +** dataBufferReplace - replace buffer's data. +*/ +typedef struct DataBuffer { + char *pData; /* Pointer to malloc'ed buffer. */ + int nCapacity; /* Size of pData buffer. */ + int nData; /* End of data loaded into pData. */ +} DataBuffer; + +static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){ + assert( nCapacity>=0 ); + pBuffer->nData = 0; + pBuffer->nCapacity = nCapacity; + pBuffer->pData = nCapacity==0 ? NULL : malloc(nCapacity); +} +static void dataBufferReset(DataBuffer *pBuffer){ + pBuffer->nData = 0; +} +static void dataBufferDestroy(DataBuffer *pBuffer){ + if( pBuffer->pData!=NULL ) free(pBuffer->pData); + SCRAMBLE(pBuffer); +} +static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){ + assert( nAddCapacity>0 ); + /* TODO(shess) Consider expanding more aggressively. Note that the + ** underlying malloc implementation may take care of such things for + ** us already. + */ + if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){ + pBuffer->nCapacity = pBuffer->nData+nAddCapacity; + pBuffer->pData = realloc(pBuffer->pData, pBuffer->nCapacity); + } +} +static void dataBufferAppend(DataBuffer *pBuffer, + const char *pSource, int nSource){ + assert( nSource>0 && pSource!=NULL ); + dataBufferExpand(pBuffer, nSource); + memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource); + pBuffer->nData += nSource; +} +static void dataBufferAppend2(DataBuffer *pBuffer, + const char *pSource1, int nSource1, + const char *pSource2, int nSource2){ + assert( nSource1>0 && pSource1!=NULL ); + assert( nSource2>0 && pSource2!=NULL ); + dataBufferExpand(pBuffer, nSource1+nSource2); + memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1); + memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2); + pBuffer->nData += nSource1+nSource2; +} +static void dataBufferReplace(DataBuffer *pBuffer, + const char *pSource, int nSource){ + dataBufferReset(pBuffer); + dataBufferAppend(pBuffer, pSource, nSource); +} + +/* StringBuffer is a null-terminated version of DataBuffer. */ +typedef struct StringBuffer { + DataBuffer b; /* Includes null terminator. */ +} StringBuffer; + +static void initStringBuffer(StringBuffer *sb){ + dataBufferInit(&sb->b, 100); + dataBufferReplace(&sb->b, "", 1); +} +static int stringBufferLength(StringBuffer *sb){ + return sb->b.nData-1; +} +static char *stringBufferData(StringBuffer *sb){ + return sb->b.pData; +} +static void stringBufferDestroy(StringBuffer *sb){ + dataBufferDestroy(&sb->b); +} + +static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){ + assert( sb->b.nData>0 ); + if( nFrom>0 ){ + sb->b.nData--; + dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1); + } +} +static void append(StringBuffer *sb, const char *zFrom){ + nappend(sb, zFrom, strlen(zFrom)); +} + +/* Append a list of strings separated by commas. */ +static void appendList(StringBuffer *sb, int nString, char **azString){ + int i; + for(i=0; i0 ) append(sb, ", "); + append(sb, azString[i]); + } +} + +static int endsInWhiteSpace(StringBuffer *p){ + return stringBufferLength(p)>0 && + safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]); +} + +/* If the StringBuffer ends in something other than white space, add a +** single space character to the end. +*/ +static void appendWhiteSpace(StringBuffer *p){ + if( stringBufferLength(p)==0 ) return; + if( !endsInWhiteSpace(p) ) append(p, " "); +} + +/* Remove white space from the end of the StringBuffer */ +static void trimWhiteSpace(StringBuffer *p){ + while( endsInWhiteSpace(p) ){ + p->b.pData[--p->b.nData-1] = '\0'; + } +} + +/*******************************************************************/ +/* DLReader is used to read document elements from a doclist. The +** current docid is cached, so dlrDocid() is fast. DLReader does not +** own the doclist buffer. +** +** dlrAtEnd - true if there's no more data to read. +** dlrDocid - docid of current document. +** dlrDocData - doclist data for current document (including docid). +** dlrDocDataBytes - length of same. +** dlrAllDataBytes - length of all remaining data. +** dlrPosData - position data for current document. +** dlrPosDataLen - length of pos data for current document (incl POS_END). +** dlrStep - step to current document. +** dlrInit - initial for doclist of given type against given data. +** dlrDestroy - clean up. +** +** Expected usage is something like: +** +** DLReader reader; +** dlrInit(&reader, pData, nData); +** while( !dlrAtEnd(&reader) ){ +** // calls to dlrDocid() and kin. +** dlrStep(&reader); +** } +** dlrDestroy(&reader); +*/ +typedef struct DLReader { + DocListType iType; + const char *pData; + int nData; + + sqlite_int64 iDocid; + int nElement; +} DLReader; + +static int dlrAtEnd(DLReader *pReader){ + assert( pReader->nData>=0 ); + return pReader->nData==0; +} +static sqlite_int64 dlrDocid(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->iDocid; +} +static const char *dlrDocData(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->pData; +} +static int dlrDocDataBytes(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->nElement; +} +static int dlrAllDataBytes(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->nData; +} +/* TODO(shess) Consider adding a field to track iDocid varint length +** to make these two functions faster. This might matter (a tiny bit) +** for queries. +*/ +static const char *dlrPosData(DLReader *pReader){ + sqlite_int64 iDummy; + int n = getVarint(pReader->pData, &iDummy); + assert( !dlrAtEnd(pReader) ); + return pReader->pData+n; +} +static int dlrPosDataLen(DLReader *pReader){ + sqlite_int64 iDummy; + int n = getVarint(pReader->pData, &iDummy); + assert( !dlrAtEnd(pReader) ); + return pReader->nElement-n; +} +static void dlrStep(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + + /* Skip past current doclist element. */ + assert( pReader->nElement<=pReader->nData ); + pReader->pData += pReader->nElement; + pReader->nData -= pReader->nElement; + + /* If there is more data, read the next doclist element. */ + if( pReader->nData!=0 ){ + sqlite_int64 iDocidDelta; + int iDummy, n = getVarint(pReader->pData, &iDocidDelta); + pReader->iDocid += iDocidDelta; + if( pReader->iType>=DL_POSITIONS ){ + assert( nnData ); + while( 1 ){ + n += getVarint32(pReader->pData+n, &iDummy); + assert( n<=pReader->nData ); + if( iDummy==POS_END ) break; + if( iDummy==POS_COLUMN ){ + n += getVarint32(pReader->pData+n, &iDummy); + assert( nnData ); + }else if( pReader->iType==DL_POSITIONS_OFFSETS ){ + n += getVarint32(pReader->pData+n, &iDummy); + n += getVarint32(pReader->pData+n, &iDummy); + assert( nnData ); + } + } + } + pReader->nElement = n; + assert( pReader->nElement<=pReader->nData ); + } +} +static void dlrInit(DLReader *pReader, DocListType iType, + const char *pData, int nData){ + assert( pData!=NULL && nData!=0 ); + pReader->iType = iType; + pReader->pData = pData; + pReader->nData = nData; + pReader->nElement = 0; + pReader->iDocid = 0; + + /* Load the first element's data. There must be a first element. */ + dlrStep(pReader); +} +static void dlrDestroy(DLReader *pReader){ + SCRAMBLE(pReader); +} + +#ifndef NDEBUG +/* Verify that the doclist can be validly decoded. Also returns the +** last docid found because it is convenient in other assertions for +** DLWriter. +*/ +static void docListValidate(DocListType iType, const char *pData, int nData, + sqlite_int64 *pLastDocid){ + sqlite_int64 iPrevDocid = 0; + assert( nData>0 ); + assert( pData!=0 ); + assert( pData+nData>pData ); + while( nData!=0 ){ + sqlite_int64 iDocidDelta; + int n = getVarint(pData, &iDocidDelta); + iPrevDocid += iDocidDelta; + if( iType>DL_DOCIDS ){ + int iDummy; + while( 1 ){ + n += getVarint32(pData+n, &iDummy); + if( iDummy==POS_END ) break; + if( iDummy==POS_COLUMN ){ + n += getVarint32(pData+n, &iDummy); + }else if( iType>DL_POSITIONS ){ + n += getVarint32(pData+n, &iDummy); + n += getVarint32(pData+n, &iDummy); + } + assert( n<=nData ); + } + } + assert( n<=nData ); + pData += n; + nData -= n; + } + if( pLastDocid ) *pLastDocid = iPrevDocid; +} +#define ASSERT_VALID_DOCLIST(i, p, n, o) docListValidate(i, p, n, o) +#else +#define ASSERT_VALID_DOCLIST(i, p, n, o) assert( 1 ) +#endif + +/*******************************************************************/ +/* DLWriter is used to write doclist data to a DataBuffer. DLWriter +** always appends to the buffer and does not own it. +** +** dlwInit - initialize to write a given type doclistto a buffer. +** dlwDestroy - clear the writer's memory. Does not free buffer. +** dlwAppend - append raw doclist data to buffer. +** dlwCopy - copy next doclist from reader to writer. +** dlwAdd - construct doclist element and append to buffer. +** Only apply dlwAdd() to DL_DOCIDS doclists (else use PLWriter). +*/ +typedef struct DLWriter { + DocListType iType; + DataBuffer *b; + sqlite_int64 iPrevDocid; +#ifndef NDEBUG + int has_iPrevDocid; +#endif +} DLWriter; + +static void dlwInit(DLWriter *pWriter, DocListType iType, DataBuffer *b){ + pWriter->b = b; + pWriter->iType = iType; + pWriter->iPrevDocid = 0; +#ifndef NDEBUG + pWriter->has_iPrevDocid = 0; +#endif +} +static void dlwDestroy(DLWriter *pWriter){ + SCRAMBLE(pWriter); +} +/* iFirstDocid is the first docid in the doclist in pData. It is +** needed because pData may point within a larger doclist, in which +** case the first item would be delta-encoded. +** +** iLastDocid is the final docid in the doclist in pData. It is +** needed to create the new iPrevDocid for future delta-encoding. The +** code could decode the passed doclist to recreate iLastDocid, but +** the only current user (docListMerge) already has decoded this +** information. +*/ +/* TODO(shess) This has become just a helper for docListMerge. +** Consider a refactor to make this cleaner. +*/ +static void dlwAppend(DLWriter *pWriter, + const char *pData, int nData, + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ + sqlite_int64 iDocid = 0; + char c[VARINT_MAX]; + int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */ +#ifndef NDEBUG + sqlite_int64 iLastDocidDelta; +#endif + + /* Recode the initial docid as delta from iPrevDocid. */ + nFirstOld = getVarint(pData, &iDocid); + assert( nFirstOldiType==DL_DOCIDS) ); + nFirstNew = putVarint(c, iFirstDocid-pWriter->iPrevDocid); + + /* Verify that the incoming doclist is valid AND that it ends with + ** the expected docid. This is essential because we'll trust this + ** docid in future delta-encoding. + */ + ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta); + assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta ); + + /* Append recoded initial docid and everything else. Rest of docids + ** should have been delta-encoded from previous initial docid. + */ + if( nFirstOldb, c, nFirstNew, + pData+nFirstOld, nData-nFirstOld); + }else{ + dataBufferAppend(pWriter->b, c, nFirstNew); + } + pWriter->iPrevDocid = iLastDocid; +} +static void dlwCopy(DLWriter *pWriter, DLReader *pReader){ + dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), + dlrDocid(pReader), dlrDocid(pReader)); +} +static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){ + char c[VARINT_MAX]; + int n = putVarint(c, iDocid-pWriter->iPrevDocid); + + /* Docids must ascend. */ + assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid ); + assert( pWriter->iType==DL_DOCIDS ); + + dataBufferAppend(pWriter->b, c, n); + pWriter->iPrevDocid = iDocid; +#ifndef NDEBUG + pWriter->has_iPrevDocid = 1; +#endif +} + +/*******************************************************************/ +/* PLReader is used to read data from a document's position list. As +** the caller steps through the list, data is cached so that varints +** only need to be decoded once. +** +** plrInit, plrDestroy - create/destroy a reader. +** plrColumn, plrPosition, plrStartOffset, plrEndOffset - accessors +** plrAtEnd - at end of stream, only call plrDestroy once true. +** plrStep - step to the next element. +*/ +typedef struct PLReader { + /* These refer to the next position's data. nData will reach 0 when + ** reading the last position, so plrStep() signals EOF by setting + ** pData to NULL. + */ + const char *pData; + int nData; + + DocListType iType; + int iColumn; /* the last column read */ + int iPosition; /* the last position read */ + int iStartOffset; /* the last start offset read */ + int iEndOffset; /* the last end offset read */ +} PLReader; + +static int plrAtEnd(PLReader *pReader){ + return pReader->pData==NULL; +} +static int plrColumn(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iColumn; +} +static int plrPosition(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iPosition; +} +static int plrStartOffset(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iStartOffset; +} +static int plrEndOffset(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iEndOffset; +} +static void plrStep(PLReader *pReader){ + int i, n; + + assert( !plrAtEnd(pReader) ); + + if( pReader->nData==0 ){ + pReader->pData = NULL; + return; + } + + n = getVarint32(pReader->pData, &i); + if( i==POS_COLUMN ){ + n += getVarint32(pReader->pData+n, &pReader->iColumn); + pReader->iPosition = 0; + pReader->iStartOffset = 0; + n += getVarint32(pReader->pData+n, &i); + } + /* Should never see adjacent column changes. */ + assert( i!=POS_COLUMN ); + + if( i==POS_END ){ + pReader->nData = 0; + pReader->pData = NULL; + return; + } + + pReader->iPosition += i-POS_BASE; + if( pReader->iType==DL_POSITIONS_OFFSETS ){ + n += getVarint32(pReader->pData+n, &i); + pReader->iStartOffset += i; + n += getVarint32(pReader->pData+n, &i); + pReader->iEndOffset = pReader->iStartOffset+i; + } + assert( n<=pReader->nData ); + pReader->pData += n; + pReader->nData -= n; +} + +static void plrInit(PLReader *pReader, DLReader *pDLReader){ + pReader->pData = dlrPosData(pDLReader); + pReader->nData = dlrPosDataLen(pDLReader); + pReader->iType = pDLReader->iType; + pReader->iColumn = 0; + pReader->iPosition = 0; + pReader->iStartOffset = 0; + pReader->iEndOffset = 0; + plrStep(pReader); +} +static void plrDestroy(PLReader *pReader){ + SCRAMBLE(pReader); +} + +/*******************************************************************/ +/* PLWriter is used in constructing a document's position list. As a +** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op. +** PLWriter writes to the associated DLWriter's buffer. +** +** plwInit - init for writing a document's poslist. +** plwDestroy - clear a writer. +** plwAdd - append position and offset information. +** plwCopy - copy next position's data from reader to writer. +** plwTerminate - add any necessary doclist terminator. +** +** Calling plwAdd() after plwTerminate() may result in a corrupt +** doclist. +*/ +/* TODO(shess) Until we've written the second item, we can cache the +** first item's information. Then we'd have three states: +** +** - initialized with docid, no positions. +** - docid and one position. +** - docid and multiple positions. +** +** Only the last state needs to actually write to dlw->b, which would +** be an improvement in the DLCollector case. +*/ +typedef struct PLWriter { + DLWriter *dlw; + + int iColumn; /* the last column written */ + int iPos; /* the last position written */ + int iOffset; /* the last start offset written */ +} PLWriter; + +/* TODO(shess) In the case where the parent is reading these values +** from a PLReader, we could optimize to a copy if that PLReader has +** the same type as pWriter. +*/ +static void plwAdd(PLWriter *pWriter, int iColumn, int iPos, + int iStartOffset, int iEndOffset){ + /* Worst-case space for POS_COLUMN, iColumn, iPosDelta, + ** iStartOffsetDelta, and iEndOffsetDelta. + */ + char c[5*VARINT_MAX]; + int n = 0; + + /* Ban plwAdd() after plwTerminate(). */ + assert( pWriter->iPos!=-1 ); + + if( pWriter->dlw->iType==DL_DOCIDS ) return; + + if( iColumn!=pWriter->iColumn ){ + n += putVarint(c+n, POS_COLUMN); + n += putVarint(c+n, iColumn); + pWriter->iColumn = iColumn; + pWriter->iPos = 0; + pWriter->iOffset = 0; + } + assert( iPos>=pWriter->iPos ); + n += putVarint(c+n, POS_BASE+(iPos-pWriter->iPos)); + pWriter->iPos = iPos; + if( pWriter->dlw->iType==DL_POSITIONS_OFFSETS ){ + assert( iStartOffset>=pWriter->iOffset ); + n += putVarint(c+n, iStartOffset-pWriter->iOffset); + pWriter->iOffset = iStartOffset; + assert( iEndOffset>=iStartOffset ); + n += putVarint(c+n, iEndOffset-iStartOffset); + } + dataBufferAppend(pWriter->dlw->b, c, n); +} +static void plwCopy(PLWriter *pWriter, PLReader *pReader){ + plwAdd(pWriter, plrColumn(pReader), plrPosition(pReader), + plrStartOffset(pReader), plrEndOffset(pReader)); +} +static void plwInit(PLWriter *pWriter, DLWriter *dlw, sqlite_int64 iDocid){ + char c[VARINT_MAX]; + int n; + + pWriter->dlw = dlw; + + /* Docids must ascend. */ + assert( !pWriter->dlw->has_iPrevDocid || iDocid>pWriter->dlw->iPrevDocid ); + n = putVarint(c, iDocid-pWriter->dlw->iPrevDocid); + dataBufferAppend(pWriter->dlw->b, c, n); + pWriter->dlw->iPrevDocid = iDocid; +#ifndef NDEBUG + pWriter->dlw->has_iPrevDocid = 1; +#endif + + pWriter->iColumn = 0; + pWriter->iPos = 0; + pWriter->iOffset = 0; +} +/* TODO(shess) Should plwDestroy() also terminate the doclist? But +** then plwDestroy() would no longer be just a destructor, it would +** also be doing work, which isn't consistent with the overall idiom. +** Another option would be for plwAdd() to always append any necessary +** terminator, so that the output is always correct. But that would +** add incremental work to the common case with the only benefit being +** API elegance. Punt for now. +*/ +static void plwTerminate(PLWriter *pWriter){ + if( pWriter->dlw->iType>DL_DOCIDS ){ + char c[VARINT_MAX]; + int n = putVarint(c, POS_END); + dataBufferAppend(pWriter->dlw->b, c, n); + } +#ifndef NDEBUG + /* Mark as terminated for assert in plwAdd(). */ + pWriter->iPos = -1; +#endif +} +static void plwDestroy(PLWriter *pWriter){ + SCRAMBLE(pWriter); +} + +/*******************************************************************/ +/* DLCollector wraps PLWriter and DLWriter to provide a +** dynamically-allocated doclist area to use during tokenization. +** +** dlcNew - malloc up and initialize a collector. +** dlcDelete - destroy a collector and all contained items. +** dlcAddPos - append position and offset information. +** dlcAddDoclist - add the collected doclist to the given buffer. +** dlcNext - terminate the current document and open another. +*/ +typedef struct DLCollector { + DataBuffer b; + DLWriter dlw; + PLWriter plw; +} DLCollector; + +/* TODO(shess) This could also be done by calling plwTerminate() and +** dataBufferAppend(). I tried that, expecting nominal performance +** differences, but it seemed to pretty reliably be worth 1% to code +** it this way. I suspect it is the incremental malloc overhead (some +** percentage of the plwTerminate() calls will cause a realloc), so +** this might be worth revisiting if the DataBuffer implementation +** changes. +*/ +static void dlcAddDoclist(DLCollector *pCollector, DataBuffer *b){ + if( pCollector->dlw.iType>DL_DOCIDS ){ + char c[VARINT_MAX]; + int n = putVarint(c, POS_END); + dataBufferAppend2(b, pCollector->b.pData, pCollector->b.nData, c, n); + }else{ + dataBufferAppend(b, pCollector->b.pData, pCollector->b.nData); + } +} +static void dlcNext(DLCollector *pCollector, sqlite_int64 iDocid){ + plwTerminate(&pCollector->plw); + plwDestroy(&pCollector->plw); + plwInit(&pCollector->plw, &pCollector->dlw, iDocid); +} +static void dlcAddPos(DLCollector *pCollector, int iColumn, int iPos, + int iStartOffset, int iEndOffset){ + plwAdd(&pCollector->plw, iColumn, iPos, iStartOffset, iEndOffset); +} + +static DLCollector *dlcNew(sqlite_int64 iDocid, DocListType iType){ + DLCollector *pCollector = malloc(sizeof(DLCollector)); + dataBufferInit(&pCollector->b, 0); + dlwInit(&pCollector->dlw, iType, &pCollector->b); + plwInit(&pCollector->plw, &pCollector->dlw, iDocid); + return pCollector; +} +static void dlcDelete(DLCollector *pCollector){ + plwDestroy(&pCollector->plw); + dlwDestroy(&pCollector->dlw); + dataBufferDestroy(&pCollector->b); + SCRAMBLE(pCollector); + free(pCollector); +} + + +/* Copy the doclist data of iType in pData/nData into *out, trimming +** unnecessary data as we go. Only columns matching iColumn are +** copied, all columns copied if iColumn is -1. Elements with no +** matching columns are dropped. The output is an iOutType doclist. +*/ +/* NOTE(shess) This code is only valid after all doclists are merged. +** If this is run before merges, then doclist items which represent +** deletion will be trimmed, and will thus not effect a deletion +** during the merge. +*/ +static void docListTrim(DocListType iType, const char *pData, int nData, + int iColumn, DocListType iOutType, DataBuffer *out){ + DLReader dlReader; + DLWriter dlWriter; + + assert( iOutType<=iType ); + + dlrInit(&dlReader, iType, pData, nData); + dlwInit(&dlWriter, iOutType, out); + + while( !dlrAtEnd(&dlReader) ){ + PLReader plReader; + PLWriter plWriter; + int match = 0; + + plrInit(&plReader, &dlReader); + + while( !plrAtEnd(&plReader) ){ + if( iColumn==-1 || plrColumn(&plReader)==iColumn ){ + if( !match ){ + plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader)); + match = 1; + } + plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader), + plrStartOffset(&plReader), plrEndOffset(&plReader)); + } + plrStep(&plReader); + } + if( match ){ + plwTerminate(&plWriter); + plwDestroy(&plWriter); + } + + plrDestroy(&plReader); + dlrStep(&dlReader); + } + dlwDestroy(&dlWriter); + dlrDestroy(&dlReader); +} + +/* Used by docListMerge() to keep doclists in the ascending order by +** docid, then ascending order by age (so the newest comes first). +*/ +typedef struct OrderedDLReader { + DLReader *pReader; + + /* TODO(shess) If we assume that docListMerge pReaders is ordered by + ** age (which we do), then we could use pReader comparisons to break + ** ties. + */ + int idx; +} OrderedDLReader; + +/* Order eof to end, then by docid asc, idx desc. */ +static int orderedDLReaderCmp(OrderedDLReader *r1, OrderedDLReader *r2){ + if( dlrAtEnd(r1->pReader) ){ + if( dlrAtEnd(r2->pReader) ) return 0; /* Both atEnd(). */ + return 1; /* Only r1 atEnd(). */ + } + if( dlrAtEnd(r2->pReader) ) return -1; /* Only r2 atEnd(). */ + + if( dlrDocid(r1->pReader)pReader) ) return -1; + if( dlrDocid(r1->pReader)>dlrDocid(r2->pReader) ) return 1; + + /* Descending on idx. */ + return r2->idx-r1->idx; +} + +/* Bubble p[0] to appropriate place in p[1..n-1]. Assumes that +** p[1..n-1] is already sorted. +*/ +/* TODO(shess) Is this frequent enough to warrant a binary search? +** Before implementing that, instrument the code to check. In most +** current usage, I expect that p[0] will be less than p[1] a very +** high proportion of the time. +*/ +static void orderedDLReaderReorder(OrderedDLReader *p, int n){ + while( n>1 && orderedDLReaderCmp(p, p+1)>0 ){ + OrderedDLReader tmp = p[0]; + p[0] = p[1]; + p[1] = tmp; + n--; + p++; + } +} + +/* Given an array of doclist readers, merge their doclist elements +** into out in sorted order (by docid), dropping elements from older +** readers when there is a duplicate docid. pReaders is assumed to be +** ordered by age, oldest first. +*/ +/* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably +** be fixed. +*/ +static void docListMerge(DataBuffer *out, + DLReader *pReaders, int nReaders){ + OrderedDLReader readers[MERGE_COUNT]; + DLWriter writer; + int i, n; + const char *pStart = 0; + int nStart = 0; + sqlite_int64 iFirstDocid = 0, iLastDocid = 0; + + assert( nReaders>0 ); + if( nReaders==1 ){ + dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); + return; + } + + assert( nReaders<=MERGE_COUNT ); + n = 0; + for(i=0; i0 ){ + orderedDLReaderReorder(readers+i, nReaders-i); + } + + dlwInit(&writer, pReaders[0].iType, out); + while( !dlrAtEnd(readers[0].pReader) ){ + sqlite_int64 iDocid = dlrDocid(readers[0].pReader); + + /* If this is a continuation of the current buffer to copy, extend + ** that buffer. memcpy() seems to be more efficient if it has a + ** lots of data to copy. + */ + if( dlrDocData(readers[0].pReader)==pStart+nStart ){ + nStart += dlrDocDataBytes(readers[0].pReader); + }else{ + if( pStart!=0 ){ + dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); + } + pStart = dlrDocData(readers[0].pReader); + nStart = dlrDocDataBytes(readers[0].pReader); + iFirstDocid = iDocid; + } + iLastDocid = iDocid; + dlrStep(readers[0].pReader); + + /* Drop all of the older elements with the same docid. */ + for(i=1; i0 ){ + orderedDLReaderReorder(readers+i, nReaders-i); + } + } + + /* Copy over any remaining elements. */ + if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); + dlwDestroy(&writer); +} + +/* Helper function for posListUnion(). Compares the current position +** between left and right, returning as standard C idiom of <0 if +** left0 if left>right, and 0 if left==right. "End" always +** compares greater. +*/ +static int posListCmp(PLReader *pLeft, PLReader *pRight){ + assert( pLeft->iType==pRight->iType ); + if( pLeft->iType==DL_DOCIDS ) return 0; + + if( plrAtEnd(pLeft) ) return plrAtEnd(pRight) ? 0 : 1; + if( plrAtEnd(pRight) ) return -1; + + if( plrColumn(pLeft)plrColumn(pRight) ) return 1; + + if( plrPosition(pLeft)plrPosition(pRight) ) return 1; + if( pLeft->iType==DL_POSITIONS ) return 0; + + if( plrStartOffset(pLeft)plrStartOffset(pRight) ) return 1; + + if( plrEndOffset(pLeft)plrEndOffset(pRight) ) return 1; + + return 0; +} + +/* Write the union of position lists in pLeft and pRight to pOut. +** "Union" in this case meaning "All unique position tuples". Should +** work with any doclist type, though both inputs and the output +** should be the same type. +*/ +static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ + PLReader left, right; + PLWriter writer; + + assert( dlrDocid(pLeft)==dlrDocid(pRight) ); + assert( pLeft->iType==pRight->iType ); + assert( pLeft->iType==pOut->iType ); + + plrInit(&left, pLeft); + plrInit(&right, pRight); + plwInit(&writer, pOut, dlrDocid(pLeft)); + + while( !plrAtEnd(&left) || !plrAtEnd(&right) ){ + int c = posListCmp(&left, &right); + if( c<0 ){ + plwCopy(&writer, &left); + plrStep(&left); + }else if( c>0 ){ + plwCopy(&writer, &right); + plrStep(&right); + }else{ + plwCopy(&writer, &left); + plrStep(&left); + plrStep(&right); + } + } + + plwTerminate(&writer); + plwDestroy(&writer); + plrDestroy(&left); + plrDestroy(&right); +} + +/* Write the union of doclists in pLeft and pRight to pOut. For +** docids in common between the inputs, the union of the position +** lists is written. Inputs and outputs are always type DL_DEFAULT. +*/ +static void docListUnion( + const char *pLeft, int nLeft, + const char *pRight, int nRight, + DataBuffer *pOut /* Write the combined doclist here */ +){ + DLReader left, right; + DLWriter writer; + + if( nLeft==0 ){ + if( nRight!=0) dataBufferAppend(pOut, pRight, nRight); + return; + } + if( nRight==0 ){ + dataBufferAppend(pOut, pLeft, nLeft); + return; + } + + dlrInit(&left, DL_DEFAULT, pLeft, nLeft); + dlrInit(&right, DL_DEFAULT, pRight, nRight); + dlwInit(&writer, DL_DEFAULT, pOut); + + while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ + if( dlrAtEnd(&right) ){ + dlwCopy(&writer, &left); + dlrStep(&left); + }else if( dlrAtEnd(&left) ){ + dlwCopy(&writer, &right); + dlrStep(&right); + }else if( dlrDocid(&left)dlrDocid(&right) ){ + dlwCopy(&writer, &right); + dlrStep(&right); + }else{ + posListUnion(&left, &right, &writer); + dlrStep(&left); + dlrStep(&right); + } + } + + dlrDestroy(&left); + dlrDestroy(&right); + dlwDestroy(&writer); +} + +/* pLeft and pRight are DLReaders positioned to the same docid. +** +** If there are no instances in pLeft or pRight where the position +** of pLeft is one less than the position of pRight, then this +** routine adds nothing to pOut. +** +** If there are one or more instances where positions from pLeft +** are exactly one less than positions from pRight, then add a new +** document record to pOut. If pOut wants to hold positions, then +** include the positions from pRight that are one more than a +** position in pLeft. In other words: pRight.iPos==pLeft.iPos+1. +*/ +static void posListPhraseMerge(DLReader *pLeft, DLReader *pRight, + DLWriter *pOut){ + PLReader left, right; + PLWriter writer; + int match = 0; + + assert( dlrDocid(pLeft)==dlrDocid(pRight) ); + assert( pOut->iType!=DL_POSITIONS_OFFSETS ); + + plrInit(&left, pLeft); + plrInit(&right, pRight); + + while( !plrAtEnd(&left) && !plrAtEnd(&right) ){ + if( plrColumn(&left)plrColumn(&right) ){ + plrStep(&right); + }else if( plrPosition(&left)+1plrPosition(&right) ){ + plrStep(&right); + }else{ + if( !match ){ + plwInit(&writer, pOut, dlrDocid(pLeft)); + match = 1; + } + plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); + plrStep(&left); + plrStep(&right); + } + } + + if( match ){ + plwTerminate(&writer); + plwDestroy(&writer); + } + + plrDestroy(&left); + plrDestroy(&right); +} + +/* We have two doclists with positions: pLeft and pRight. +** Write the phrase intersection of these two doclists into pOut. +** +** A phrase intersection means that two documents only match +** if pLeft.iPos+1==pRight.iPos. +** +** iType controls the type of data written to pOut. If iType is +** DL_POSITIONS, the positions are those from pRight. +*/ +static void docListPhraseMerge( + const char *pLeft, int nLeft, + const char *pRight, int nRight, + DocListType iType, + DataBuffer *pOut /* Write the combined doclist here */ +){ + DLReader left, right; + DLWriter writer; + + if( nLeft==0 || nRight==0 ) return; + + assert( iType!=DL_POSITIONS_OFFSETS ); + + dlrInit(&left, DL_POSITIONS, pLeft, nLeft); + dlrInit(&right, DL_POSITIONS, pRight, nRight); + dlwInit(&writer, iType, pOut); + + while( !dlrAtEnd(&left) && !dlrAtEnd(&right) ){ + if( dlrDocid(&left) one AND (two OR three) + * [one OR two three] ==> (one OR two) AND three + * + * A "-" before a term matches all entries that lack that term. + * The "-" must occur immediately before the term with in intervening + * space. This is how the search engines do it. + * + * A NOT term cannot be the right-hand operand of an OR. If this + * occurs in the query string, the NOT is ignored: + * + * [one OR -two] ==> one OR two + * + */ +typedef struct Query { + fulltext_vtab *pFts; /* The full text index */ + int nTerms; /* Number of terms in the query */ + QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */ + int nextIsOr; /* Set the isOr flag on the next inserted term */ + int nextColumn; /* Next word parsed must be in this column */ + int dfltColumn; /* The default column */ +} Query; + + +/* +** An instance of the following structure keeps track of generated +** matching-word offset information and snippets. +*/ +typedef struct Snippet { + int nMatch; /* Total number of matches */ + int nAlloc; /* Space allocated for aMatch[] */ + struct snippetMatch { /* One entry for each matching term */ + char snStatus; /* Status flag for use while constructing snippets */ + short int iCol; /* The column that contains the match */ + short int iTerm; /* The index in Query.pTerms[] of the matching term */ + short int nByte; /* Number of bytes in the term */ + int iStart; /* The offset to the first character of the term */ + } *aMatch; /* Points to space obtained from malloc */ + char *zOffset; /* Text rendering of aMatch[] */ + int nOffset; /* strlen(zOffset) */ + char *zSnippet; /* Snippet text */ + int nSnippet; /* strlen(zSnippet) */ +} Snippet; + + +typedef enum QueryType { + QUERY_GENERIC, /* table scan */ + QUERY_ROWID, /* lookup by rowid */ + QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/ +} QueryType; + +typedef enum fulltext_statement { + CONTENT_INSERT_STMT, + CONTENT_SELECT_STMT, + CONTENT_UPDATE_STMT, + CONTENT_DELETE_STMT, + + BLOCK_INSERT_STMT, + BLOCK_SELECT_STMT, + BLOCK_DELETE_STMT, + + SEGDIR_MAX_INDEX_STMT, + SEGDIR_SET_STMT, + SEGDIR_SELECT_STMT, + SEGDIR_SPAN_STMT, + SEGDIR_DELETE_STMT, + SEGDIR_SELECT_ALL_STMT, + + MAX_STMT /* Always at end! */ +} fulltext_statement; + +/* These must exactly match the enum above. */ +/* TODO(shess): Is there some risk that a statement will be used in two +** cursors at once, e.g. if a query joins a virtual table to itself? +** If so perhaps we should move some of these to the cursor object. +*/ +static const char *const fulltext_zStatement[MAX_STMT] = { + /* CONTENT_INSERT */ NULL, /* generated in contentInsertStatement() */ + /* CONTENT_SELECT */ "select * from %_content where rowid = ?", + /* CONTENT_UPDATE */ NULL, /* generated in contentUpdateStatement() */ + /* CONTENT_DELETE */ "delete from %_content where rowid = ?", + + /* BLOCK_INSERT */ "insert into %_segments values (?)", + /* BLOCK_SELECT */ "select block from %_segments where rowid = ?", + /* BLOCK_DELETE */ "delete from %_segments where rowid between ? and ?", + + /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?", + /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)", + /* SEGDIR_SELECT */ + "select start_block, leaves_end_block, root from %_segdir " + " where level = ? order by idx", + /* SEGDIR_SPAN */ + "select min(start_block), max(end_block) from %_segdir " + " where level = ? and start_block <> 0", + /* SEGDIR_DELETE */ "delete from %_segdir where level = ?", + /* SEGDIR_SELECT_ALL */ + "select root, leaves_end_block from %_segdir order by level desc, idx", +}; + +/* +** A connection to a fulltext index is an instance of the following +** structure. The xCreate and xConnect methods create an instance +** of this structure and xDestroy and xDisconnect free that instance. +** All other methods receive a pointer to the structure as one of their +** arguments. +*/ +struct fulltext_vtab { + sqlite3_vtab base; /* Base class used by SQLite core */ + sqlite3 *db; /* The database connection */ + const char *zDb; /* logical database name */ + const char *zName; /* virtual table name */ + int nColumn; /* number of columns in virtual table */ + char **azColumn; /* column names. malloced */ + char **azContentColumn; /* column names in content table; malloced */ + sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ + + /* Precompiled statements which we keep as long as the table is + ** open. + */ + sqlite3_stmt *pFulltextStatements[MAX_STMT]; + + /* Precompiled statements used for segment merges. We run a + ** separate select across the leaf level of each tree being merged. + */ + sqlite3_stmt *pLeafSelectStmts[MERGE_COUNT]; + /* The statement used to prepare pLeafSelectStmts. */ +#define LEAF_SELECT \ + "select block from %_segments where rowid between ? and ? order by rowid" + + /* These buffer pending index updates during transactions. + ** nPendingData estimates the memory size of the pending data. It + ** doesn't include the hash-bucket overhead, nor any malloc + ** overhead. When nPendingData exceeds kPendingThreshold, the + ** buffer is flushed even before the transaction closes. + ** pendingTerms stores the data, and is only valid when nPendingData + ** is >=0 (nPendingData<0 means pendingTerms has not been + ** initialized). iPrevDocid is the last docid written, used to make + ** certain we're inserting in sorted order. + */ + int nPendingData; +#define kPendingThreshold (1*1024*1024) + sqlite_int64 iPrevDocid; + fts2Hash pendingTerms; +}; + +/* +** When the core wants to do a query, it create a cursor using a +** call to xOpen. This structure is an instance of a cursor. It +** is destroyed by xClose. +*/ +typedef struct fulltext_cursor { + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ + QueryType iCursorType; /* Copy of sqlite3_index_info.idxNum */ + sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ + int eof; /* True if at End Of Results */ + Query q; /* Parsed query string */ + Snippet snippet; /* Cached snippet for the current row */ + int iColumn; /* Column being searched */ + DataBuffer result; /* Doclist results from fulltextQuery */ + DLReader reader; /* Result reader if result not empty */ +} fulltext_cursor; + +static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){ + return (fulltext_vtab *) c->base.pVtab; +} + +static const sqlite3_module fts2Module; /* forward declaration */ + +/* Return a dynamically generated statement of the form + * insert into %_content (rowid, ...) values (?, ...) + */ +static const char *contentInsertStatement(fulltext_vtab *v){ + StringBuffer sb; + int i; + + initStringBuffer(&sb); + append(&sb, "insert into %_content (rowid, "); + appendList(&sb, v->nColumn, v->azContentColumn); + append(&sb, ") values (?"); + for(i=0; inColumn; ++i) + append(&sb, ", ?"); + append(&sb, ")"); + return stringBufferData(&sb); +} + +/* Return a dynamically generated statement of the form + * update %_content set [col_0] = ?, [col_1] = ?, ... + * where rowid = ? + */ +static const char *contentUpdateStatement(fulltext_vtab *v){ + StringBuffer sb; + int i; + + initStringBuffer(&sb); + append(&sb, "update %_content set "); + for(i=0; inColumn; ++i) { + if( i>0 ){ + append(&sb, ", "); + } + append(&sb, v->azContentColumn[i]); + append(&sb, " = ?"); + } + append(&sb, " where rowid = ?"); + return stringBufferData(&sb); +} + +/* Puts a freshly-prepared statement determined by iStmt in *ppStmt. +** If the indicated statement has never been prepared, it is prepared +** and cached, otherwise the cached version is reset. +*/ +static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + assert( iStmtpFulltextStatements[iStmt]==NULL ){ + const char *zStmt; + int rc; + switch( iStmt ){ + case CONTENT_INSERT_STMT: + zStmt = contentInsertStatement(v); break; + case CONTENT_UPDATE_STMT: + zStmt = contentUpdateStatement(v); break; + default: + zStmt = fulltext_zStatement[iStmt]; + } + rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt], + zStmt); + if( zStmt != fulltext_zStatement[iStmt]) free((void *) zStmt); + if( rc!=SQLITE_OK ) return rc; + } else { + int rc = sqlite3_reset(v->pFulltextStatements[iStmt]); + if( rc!=SQLITE_OK ) return rc; + } + + *ppStmt = v->pFulltextStatements[iStmt]; + return SQLITE_OK; +} + +/* Like sqlite3_step(), but convert SQLITE_DONE to SQLITE_OK and +** SQLITE_ROW to SQLITE_ERROR. Useful for statements like UPDATE, +** where we expect no results. +*/ +static int sql_single_step(sqlite3_stmt *s){ + int rc = sqlite3_step(s); + return (rc==SQLITE_DONE) ? SQLITE_OK : rc; +} + +/* Like sql_get_statement(), but for special replicated LEAF_SELECT +** statements. +*/ +/* TODO(shess) Write version for generic statements and then share +** that between the cached-statement functions. +*/ +static int sql_get_leaf_statement(fulltext_vtab *v, int idx, + sqlite3_stmt **ppStmt){ + assert( idx>=0 && idxpLeafSelectStmts[idx]==NULL ){ + int rc = sql_prepare(v->db, v->zDb, v->zName, &v->pLeafSelectStmts[idx], + LEAF_SELECT); + if( rc!=SQLITE_OK ) return rc; + }else{ + int rc = sqlite3_reset(v->pLeafSelectStmts[idx]); + if( rc!=SQLITE_OK ) return rc; + } + + *ppStmt = v->pLeafSelectStmts[idx]; + return SQLITE_OK; +} + +/* insert into %_content (rowid, ...) values ([rowid], [pValues]) */ +static int content_insert(fulltext_vtab *v, sqlite3_value *rowid, + sqlite3_value **pValues){ + sqlite3_stmt *s; + int i; + int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_value(s, 1, rowid); + if( rc!=SQLITE_OK ) return rc; + + for(i=0; inColumn; ++i){ + rc = sqlite3_bind_value(s, 2+i, pValues[i]); + if( rc!=SQLITE_OK ) return rc; + } + + return sql_single_step(s); +} + +/* update %_content set col0 = pValues[0], col1 = pValues[1], ... + * where rowid = [iRowid] */ +static int content_update(fulltext_vtab *v, sqlite3_value **pValues, + sqlite_int64 iRowid){ + sqlite3_stmt *s; + int i; + int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + for(i=0; inColumn; ++i){ + rc = sqlite3_bind_value(s, 1+i, pValues[i]); + if( rc!=SQLITE_OK ) return rc; + } + + rc = sqlite3_bind_int64(s, 1+v->nColumn, iRowid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +static void freeStringArray(int nString, const char **pString){ + int i; + + for (i=0 ; i < nString ; ++i) { + if( pString[i]!=NULL ) free((void *) pString[i]); + } + free((void *) pString); +} + +/* select * from %_content where rowid = [iRow] + * The caller must delete the returned array and all strings in it. + * null fields will be NULL in the returned array. + * + * TODO: Perhaps we should return pointer/length strings here for consistency + * with other code which uses pointer/length. */ +static int content_select(fulltext_vtab *v, sqlite_int64 iRow, + const char ***pValues){ + sqlite3_stmt *s; + const char **values; + int i; + int rc; + + *pValues = NULL; + + rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc!=SQLITE_ROW ) return rc; + + values = (const char **) malloc(v->nColumn * sizeof(const char *)); + for(i=0; inColumn; ++i){ + if( sqlite3_column_type(s, i)==SQLITE_NULL ){ + values[i] = NULL; + }else{ + values[i] = string_dup((char*)sqlite3_column_text(s, i)); + } + } + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ){ + *pValues = values; + return SQLITE_OK; + } + + freeStringArray(v->nColumn, values); + return rc; +} + +/* delete from %_content where rowid = [iRow ] */ +static int content_delete(fulltext_vtab *v, sqlite_int64 iRow){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iRow); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* insert into %_segments values ([pData]) +** returns assigned rowid in *piBlockid +*/ +static int block_insert(fulltext_vtab *v, const char *pData, int nData, + sqlite_int64 *piBlockid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + + *piBlockid = sqlite3_last_insert_rowid(v->db); + return SQLITE_OK; +} + +/* delete from %_segments +** where rowid between [iStartBlockid] and [iEndBlockid] +** +** Deletes the range of blocks, inclusive, used to delete the blocks +** which form a segment. +*/ +static int block_delete(fulltext_vtab *v, + sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iStartBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found +** at iLevel. Returns SQLITE_DONE if there are no segments at +** iLevel. Otherwise returns an error. +*/ +static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + /* Should always get at least one row due to how max() works. */ + if( rc==SQLITE_DONE ) return SQLITE_DONE; + if( rc!=SQLITE_ROW ) return rc; + + /* NULL means that there were no inputs to max(). */ + if( SQLITE_NULL==sqlite3_column_type(s, 0) ){ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + return rc; + } + + *pidx = sqlite3_column_int(s, 0); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + return SQLITE_ROW; +} + +/* insert into %_segdir values ( +** [iLevel], [idx], +** [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid], +** [pRootData] +** ) +*/ +static int segdir_set(fulltext_vtab *v, int iLevel, int idx, + sqlite_int64 iStartBlockid, + sqlite_int64 iLeavesEndBlockid, + sqlite_int64 iEndBlockid, + const char *pRootData, int nRootData){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 2, idx); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 3, iStartBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 5, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* Queries %_segdir for the block span of the segments in level +** iLevel. Returns SQLITE_DONE if there are no blocks for iLevel, +** SQLITE_ROW if there are blocks, else an error. +*/ +static int segdir_span(fulltext_vtab *v, int iLevel, + sqlite_int64 *piStartBlockid, + sqlite_int64 *piEndBlockid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ) return SQLITE_DONE; /* Should never happen */ + if( rc!=SQLITE_ROW ) return rc; + + /* This happens if all segments at this level are entirely inline. */ + if( SQLITE_NULL==sqlite3_column_type(s, 0) ){ + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + int rc2 = sqlite3_step(s); + if( rc2==SQLITE_ROW ) return SQLITE_ERROR; + return rc2; + } + + *piStartBlockid = sqlite3_column_int64(s, 0); + *piEndBlockid = sqlite3_column_int64(s, 1); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + return SQLITE_ROW; +} + +/* Delete the segment blocks and segment directory records for all +** segments at iLevel. +*/ +static int segdir_delete(fulltext_vtab *v, int iLevel){ + sqlite3_stmt *s; + sqlite_int64 iStartBlockid, iEndBlockid; + int rc = segdir_span(v, iLevel, &iStartBlockid, &iEndBlockid); + if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc; + + if( rc==SQLITE_ROW ){ + rc = block_delete(v, iStartBlockid, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + } + + /* Delete the segment directory itself. */ + rc = sql_get_statement(v, SEGDIR_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* TODO(shess) clearPendingTerms() is far down the file because +** writeZeroSegment() is far down the file because LeafWriter is far +** down the file. Consider refactoring the code to move the non-vtab +** code above the vtab code so that we don't need this forward +** reference. +*/ +static int clearPendingTerms(fulltext_vtab *v); + +/* +** Free the memory used to contain a fulltext_vtab structure. +*/ +static void fulltext_vtab_destroy(fulltext_vtab *v){ + int iStmt, i; + + TRACE(("FTS2 Destroy %p\n", v)); + for( iStmt=0; iStmtpFulltextStatements[iStmt]!=NULL ){ + sqlite3_finalize(v->pFulltextStatements[iStmt]); + v->pFulltextStatements[iStmt] = NULL; + } + } + + for( i=0; ipLeafSelectStmts[i]!=NULL ){ + sqlite3_finalize(v->pLeafSelectStmts[i]); + v->pLeafSelectStmts[i] = NULL; + } + } + + if( v->pTokenizer!=NULL ){ + v->pTokenizer->pModule->xDestroy(v->pTokenizer); + v->pTokenizer = NULL; + } + + clearPendingTerms(v); + + free(v->azColumn); + for(i = 0; i < v->nColumn; ++i) { + sqlite3_free(v->azContentColumn[i]); + } + free(v->azContentColumn); + free(v); +} + +/* +** Token types for parsing the arguments to xConnect or xCreate. +*/ +#define TOKEN_EOF 0 /* End of file */ +#define TOKEN_SPACE 1 /* Any kind of whitespace */ +#define TOKEN_ID 2 /* An identifier */ +#define TOKEN_STRING 3 /* A string literal */ +#define TOKEN_PUNCT 4 /* A single punctuation character */ + +/* +** If X is a character that can be used in an identifier then +** IdChar(X) will be true. Otherwise it is false. +** +** For ASCII, any character with the high-order bit set is +** allowed in an identifier. For 7-bit characters, +** sqlite3IsIdChar[X] must be 1. +** +** Ticket #1066. the SQL standard does not allow '$' in the +** middle of identfiers. But many SQL implementations do. +** SQLite will allow '$' in identifiers for compatibility. +** But the feature is undocumented. +*/ +static const char isIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isIdChar[c-0x20])) + + +/* +** Return the length of the token that begins at z[0]. +** Store the token type in *tokenType before returning. +*/ +static int getToken(const char *z, int *tokenType){ + int i, c; + switch( *z ){ + case 0: { + *tokenType = TOKEN_EOF; + return 0; + } + case ' ': case '\t': case '\n': case '\f': case '\r': { + for(i=1; safe_isspace(z[i]); i++){} + *tokenType = TOKEN_SPACE; + return i; + } + case '`': + case '\'': + case '"': { + int delim = z[0]; + for(i=1; (c=z[i])!=0; i++){ + if( c==delim ){ + if( z[i+1]==delim ){ + i++; + }else{ + break; + } + } + } + *tokenType = TOKEN_STRING; + return i + (c!=0); + } + case '[': { + for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} + *tokenType = TOKEN_ID; + return i; + } + default: { + if( !IdChar(*z) ){ + break; + } + for(i=1; IdChar(z[i]); i++){} + *tokenType = TOKEN_ID; + return i; + } + } + *tokenType = TOKEN_PUNCT; + return 1; +} + +/* +** A token extracted from a string is an instance of the following +** structure. +*/ +typedef struct Token { + const char *z; /* Pointer to token text. Not '\000' terminated */ + short int n; /* Length of the token text in bytes. */ +} Token; + +/* +** Given a input string (which is really one of the argv[] parameters +** passed into xConnect or xCreate) split the string up into tokens. +** Return an array of pointers to '\000' terminated strings, one string +** for each non-whitespace token. +** +** The returned array is terminated by a single NULL pointer. +** +** Space to hold the returned array is obtained from a single +** malloc and should be freed by passing the return value to free(). +** The individual strings within the token list are all a part of +** the single memory allocation and will all be freed at once. +*/ +static char **tokenizeString(const char *z, int *pnToken){ + int nToken = 0; + Token *aToken = malloc( strlen(z) * sizeof(aToken[0]) ); + int n = 1; + int e, i; + int totalSize = 0; + char **azToken; + char *zCopy; + while( n>0 ){ + n = getToken(z, &e); + if( e!=TOKEN_SPACE ){ + aToken[nToken].z = z; + aToken[nToken].n = n; + nToken++; + totalSize += n+1; + } + z += n; + } + azToken = (char**)malloc( nToken*sizeof(char*) + totalSize ); + zCopy = (char*)&azToken[nToken]; + nToken--; + for(i=0; i=0 ){ + azIn[j] = azIn[i]; + } + j++; + } + } + azIn[j] = 0; + } +} + + +/* +** Find the first alphanumeric token in the string zIn. Null-terminate +** this token. Remove any quotation marks. And return a pointer to +** the result. +*/ +static char *firstToken(char *zIn, char **pzTail){ + int n, ttype; + while(1){ + n = getToken(zIn, &ttype); + if( ttype==TOKEN_SPACE ){ + zIn += n; + }else if( ttype==TOKEN_EOF ){ + *pzTail = zIn; + return 0; + }else{ + zIn[n] = 0; + *pzTail = &zIn[1]; + dequoteString(zIn); + return zIn; + } + } + /*NOTREACHED*/ +} + +/* Return true if... +** +** * s begins with the string t, ignoring case +** * s is longer than t +** * The first character of s beyond t is not a alphanumeric +** +** Ignore leading space in *s. +** +** To put it another way, return true if the first token of +** s[] is t[]. +*/ +static int startsWith(const char *s, const char *t){ + while( safe_isspace(*s) ){ s++; } + while( *t ){ + if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0; + } + return *s!='_' && !safe_isalnum(*s); +} + +/* +** An instance of this structure defines the "spec" of a +** full text index. This structure is populated by parseSpec +** and use by fulltextConnect and fulltextCreate. +*/ +typedef struct TableSpec { + const char *zDb; /* Logical database name */ + const char *zName; /* Name of the full-text index */ + int nColumn; /* Number of columns to be indexed */ + char **azColumn; /* Original names of columns to be indexed */ + char **azContentColumn; /* Column names for %_content */ + char **azTokenizer; /* Name of tokenizer and its arguments */ +} TableSpec; + +/* +** Reclaim all of the memory used by a TableSpec +*/ +static void clearTableSpec(TableSpec *p) { + free(p->azColumn); + free(p->azContentColumn); + free(p->azTokenizer); +} + +/* Parse a CREATE VIRTUAL TABLE statement, which looks like this: + * + * CREATE VIRTUAL TABLE email + * USING fts2(subject, body, tokenize mytokenizer(myarg)) + * + * We return parsed information in a TableSpec structure. + * + */ +static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv, + char**pzErr){ + int i, n; + char *z, *zDummy; + char **azArg; + const char *zTokenizer = 0; /* argv[] entry describing the tokenizer */ + + assert( argc>=3 ); + /* Current interface: + ** argv[0] - module name + ** argv[1] - database name + ** argv[2] - table name + ** argv[3..] - columns, optionally followed by tokenizer specification + ** and snippet delimiters specification. + */ + + /* Make a copy of the complete argv[][] array in a single allocation. + ** The argv[][] array is read-only and transient. We can write to the + ** copy in order to modify things and the copy is persistent. + */ + CLEAR(pSpec); + for(i=n=0; izDb = azArg[1]; + pSpec->zName = azArg[2]; + pSpec->nColumn = 0; + pSpec->azColumn = azArg; + zTokenizer = "tokenize simple"; + for(i=3; inColumn] = firstToken(azArg[i], &zDummy); + pSpec->nColumn++; + } + } + if( pSpec->nColumn==0 ){ + azArg[0] = "content"; + pSpec->nColumn = 1; + } + + /* + ** Construct the list of content column names. + ** + ** Each content column name will be of the form cNNAAAA + ** where NN is the column number and AAAA is the sanitized + ** column name. "sanitized" means that special characters are + ** converted to "_". The cNN prefix guarantees that all column + ** names are unique. + ** + ** The AAAA suffix is not strictly necessary. It is included + ** for the convenience of people who might examine the generated + ** %_content table and wonder what the columns are used for. + */ + pSpec->azContentColumn = malloc( pSpec->nColumn * sizeof(char *) ); + if( pSpec->azContentColumn==0 ){ + clearTableSpec(pSpec); + return SQLITE_NOMEM; + } + for(i=0; inColumn; i++){ + char *p; + pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]); + for (p = pSpec->azContentColumn[i]; *p ; ++p) { + if( !safe_isalnum(*p) ) *p = '_'; + } + } + + /* + ** Parse the tokenizer specification string. + */ + pSpec->azTokenizer = tokenizeString(zTokenizer, &n); + tokenListToIdList(pSpec->azTokenizer); + + return SQLITE_OK; +} + +/* +** Generate a CREATE TABLE statement that describes the schema of +** the virtual table. Return a pointer to this schema string. +** +** Space is obtained from sqlite3_mprintf() and should be freed +** using sqlite3_free(). +*/ +static char *fulltextSchema( + int nColumn, /* Number of columns */ + const char *const* azColumn, /* List of columns */ + const char *zTableName /* Name of the table */ +){ + int i; + char *zSchema, *zNext; + const char *zSep = "("; + zSchema = sqlite3_mprintf("CREATE TABLE x"); + for(i=0; ibase */ + v->db = db; + v->zDb = spec->zDb; /* Freed when azColumn is freed */ + v->zName = spec->zName; /* Freed when azColumn is freed */ + v->nColumn = spec->nColumn; + v->azContentColumn = spec->azContentColumn; + spec->azContentColumn = 0; + v->azColumn = spec->azColumn; + spec->azColumn = 0; + + if( spec->azTokenizer==0 ){ + return SQLITE_NOMEM; + } + + zTok = spec->azTokenizer[0]; + if( !zTok ){ + zTok = "simple"; + } + nTok = strlen(zTok)+1; + + m = (sqlite3_tokenizer_module *)sqlite3Fts2HashFind(pHash, zTok, nTok); + if( !m ){ + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]); + rc = SQLITE_ERROR; + goto err; + } + + for(n=0; spec->azTokenizer[n]; n++){} + if( n ){ + rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1], + &v->pTokenizer); + }else{ + rc = m->xCreate(0, 0, &v->pTokenizer); + } + if( rc!=SQLITE_OK ) goto err; + v->pTokenizer->pModule = m; + + /* TODO: verify the existence of backing tables foo_content, foo_term */ + + schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn, + spec->zName); + rc = sqlite3_declare_vtab(db, schema); + sqlite3_free(schema); + if( rc!=SQLITE_OK ) goto err; + + memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); + + /* Indicate that the buffer is not live. */ + v->nPendingData = -1; + + *ppVTab = &v->base; + TRACE(("FTS2 Connect %p\n", v)); + + return rc; + +err: + fulltext_vtab_destroy(v); + return rc; +} + +static int fulltextConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, + char **pzErr +){ + TableSpec spec; + int rc = parseSpec(&spec, argc, argv, pzErr); + if( rc!=SQLITE_OK ) return rc; + + rc = constructVtab(db, (fts2Hash *)pAux, &spec, ppVTab, pzErr); + clearTableSpec(&spec); + return rc; +} + +/* The %_content table holds the text of each document, with +** the rowid used as the docid. +*/ +/* TODO(shess) This comment needs elaboration to match the updated +** code. Work it into the top-of-file comment at that time. +*/ +static int fulltextCreate(sqlite3 *db, void *pAux, + int argc, const char * const *argv, + sqlite3_vtab **ppVTab, char **pzErr){ + int rc; + TableSpec spec; + StringBuffer schema; + TRACE(("FTS2 Create\n")); + + rc = parseSpec(&spec, argc, argv, pzErr); + if( rc!=SQLITE_OK ) return rc; + + initStringBuffer(&schema); + append(&schema, "CREATE TABLE %_content("); + appendList(&schema, spec.nColumn, spec.azContentColumn); + append(&schema, ")"); + rc = sql_exec(db, spec.zDb, spec.zName, stringBufferData(&schema)); + stringBufferDestroy(&schema); + if( rc!=SQLITE_OK ) goto out; + + rc = sql_exec(db, spec.zDb, spec.zName, + "create table %_segments(block blob);"); + if( rc!=SQLITE_OK ) goto out; + + rc = sql_exec(db, spec.zDb, spec.zName, + "create table %_segdir(" + " level integer," + " idx integer," + " start_block integer," + " leaves_end_block integer," + " end_block integer," + " root blob," + " primary key(level, idx)" + ");"); + if( rc!=SQLITE_OK ) goto out; + + rc = constructVtab(db, (fts2Hash *)pAux, &spec, ppVTab, pzErr); + +out: + clearTableSpec(&spec); + return rc; +} + +/* Decide how to handle an SQL query. */ +static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ + int i; + TRACE(("FTS2 BestIndex\n")); + + for(i=0; inConstraint; ++i){ + const struct sqlite3_index_constraint *pConstraint; + pConstraint = &pInfo->aConstraint[i]; + if( pConstraint->usable ) { + if( pConstraint->iColumn==-1 && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + pInfo->idxNum = QUERY_ROWID; /* lookup by rowid */ + TRACE(("FTS2 QUERY_ROWID\n")); + } else if( pConstraint->iColumn>=0 && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ + /* full-text search */ + pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn; + TRACE(("FTS2 QUERY_FULLTEXT %d\n", pConstraint->iColumn)); + } else continue; + + pInfo->aConstraintUsage[i].argvIndex = 1; + pInfo->aConstraintUsage[i].omit = 1; + + /* An arbitrary value for now. + * TODO: Perhaps rowid matches should be considered cheaper than + * full-text searches. */ + pInfo->estimatedCost = 1.0; + + return SQLITE_OK; + } + } + pInfo->idxNum = QUERY_GENERIC; + return SQLITE_OK; +} + +static int fulltextDisconnect(sqlite3_vtab *pVTab){ + TRACE(("FTS2 Disconnect %p\n", pVTab)); + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextDestroy(sqlite3_vtab *pVTab){ + fulltext_vtab *v = (fulltext_vtab *)pVTab; + int rc; + + TRACE(("FTS2 Destroy %p\n", pVTab)); + rc = sql_exec(v->db, v->zDb, v->zName, + "drop table if exists %_content;" + "drop table if exists %_segments;" + "drop table if exists %_segdir;" + ); + if( rc!=SQLITE_OK ) return rc; + + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + fulltext_cursor *c; + + c = (fulltext_cursor *) calloc(sizeof(fulltext_cursor), 1); + /* sqlite will initialize c->base */ + *ppCursor = &c->base; + TRACE(("FTS2 Open %p: %p\n", pVTab, c)); + + return SQLITE_OK; +} + + +/* Free all of the dynamically allocated memory held by *q +*/ +static void queryClear(Query *q){ + int i; + for(i = 0; i < q->nTerms; ++i){ + free(q->pTerms[i].pTerm); + } + free(q->pTerms); + CLEAR(q); +} + +/* Free all of the dynamically allocated memory held by the +** Snippet +*/ +static void snippetClear(Snippet *p){ + free(p->aMatch); + free(p->zOffset); + free(p->zSnippet); + CLEAR(p); +} +/* +** Append a single entry to the p->aMatch[] log. +*/ +static void snippetAppendMatch( + Snippet *p, /* Append the entry to this snippet */ + int iCol, int iTerm, /* The column and query term */ + int iStart, int nByte /* Offset and size of the match */ +){ + int i; + struct snippetMatch *pMatch; + if( p->nMatch+1>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + 10; + p->aMatch = realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); + if( p->aMatch==0 ){ + p->nMatch = 0; + p->nAlloc = 0; + return; + } + } + i = p->nMatch++; + pMatch = &p->aMatch[i]; + pMatch->iCol = iCol; + pMatch->iTerm = iTerm; + pMatch->iStart = iStart; + pMatch->nByte = nByte; +} + +/* +** Sizing information for the circular buffer used in snippetOffsetsOfColumn() +*/ +#define FTS2_ROTOR_SZ (32) +#define FTS2_ROTOR_MASK (FTS2_ROTOR_SZ-1) + +/* +** Add entries to pSnippet->aMatch[] for every match that occurs against +** document zDoc[0..nDoc-1] which is stored in column iColumn. +*/ +static void snippetOffsetsOfColumn( + Query *pQuery, + Snippet *pSnippet, + int iColumn, + const char *zDoc, + int nDoc +){ + const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */ + sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */ + sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */ + fulltext_vtab *pVtab; /* The full text index */ + int nColumn; /* Number of columns in the index */ + const QueryTerm *aTerm; /* Query string terms */ + int nTerm; /* Number of query string terms */ + int i, j; /* Loop counters */ + int rc; /* Return code */ + unsigned int match, prevMatch; /* Phrase search bitmasks */ + const char *zToken; /* Next token from the tokenizer */ + int nToken; /* Size of zToken */ + int iBegin, iEnd, iPos; /* Offsets of beginning and end */ + + /* The following variables keep a circular buffer of the last + ** few tokens */ + unsigned int iRotor = 0; /* Index of current token */ + int iRotorBegin[FTS2_ROTOR_SZ]; /* Beginning offset of token */ + int iRotorLen[FTS2_ROTOR_SZ]; /* Length of token */ + + pVtab = pQuery->pFts; + nColumn = pVtab->nColumn; + pTokenizer = pVtab->pTokenizer; + pTModule = pTokenizer->pModule; + rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); + if( rc ) return; + pTCursor->pTokenizer = pTokenizer; + aTerm = pQuery->pTerms; + nTerm = pQuery->nTerms; + if( nTerm>=FTS2_ROTOR_SZ ){ + nTerm = FTS2_ROTOR_SZ - 1; + } + prevMatch = 0; + while(1){ + rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos); + if( rc ) break; + iRotorBegin[iRotor&FTS2_ROTOR_MASK] = iBegin; + iRotorLen[iRotor&FTS2_ROTOR_MASK] = iEnd-iBegin; + match = 0; + for(i=0; i=0 && iColnToken ) continue; + if( !aTerm[i].isPrefix && aTerm[i].nTerm1 && (prevMatch & (1<=0; j--){ + int k = (iRotor-j) & FTS2_ROTOR_MASK; + snippetAppendMatch(pSnippet, iColumn, i-j, + iRotorBegin[k], iRotorLen[k]); + } + } + } + prevMatch = match<<1; + iRotor++; + } + pTModule->xClose(pTCursor); +} + + +/* +** Compute all offsets for the current row of the query. +** If the offsets have already been computed, this routine is a no-op. +*/ +static void snippetAllOffsets(fulltext_cursor *p){ + int nColumn; + int iColumn, i; + int iFirst, iLast; + fulltext_vtab *pFts; + + if( p->snippet.nMatch ) return; + if( p->q.nTerms==0 ) return; + pFts = p->q.pFts; + nColumn = pFts->nColumn; + iColumn = (p->iCursorType - QUERY_FULLTEXT); + if( iColumn<0 || iColumn>=nColumn ){ + iFirst = 0; + iLast = nColumn-1; + }else{ + iFirst = iColumn; + iLast = iColumn; + } + for(i=iFirst; i<=iLast; i++){ + const char *zDoc; + int nDoc; + zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1); + nDoc = sqlite3_column_bytes(p->pStmt, i+1); + snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc); + } +} + +/* +** Convert the information in the aMatch[] array of the snippet +** into the string zOffset[0..nOffset-1]. +*/ +static void snippetOffsetText(Snippet *p){ + int i; + int cnt = 0; + StringBuffer sb; + char zBuf[200]; + if( p->zOffset ) return; + initStringBuffer(&sb); + for(i=0; inMatch; i++){ + struct snippetMatch *pMatch = &p->aMatch[i]; + zBuf[0] = ' '; + sprintf(&zBuf[cnt>0], "%d %d %d %d", pMatch->iCol, + pMatch->iTerm, pMatch->iStart, pMatch->nByte); + append(&sb, zBuf); + cnt++; + } + p->zOffset = stringBufferData(&sb); + p->nOffset = stringBufferLength(&sb); +} + +/* +** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set +** of matching words some of which might be in zDoc. zDoc is column +** number iCol. +** +** iBreak is suggested spot in zDoc where we could begin or end an +** excerpt. Return a value similar to iBreak but possibly adjusted +** to be a little left or right so that the break point is better. +*/ +static int wordBoundary( + int iBreak, /* The suggested break point */ + const char *zDoc, /* Document text */ + int nDoc, /* Number of bytes in zDoc[] */ + struct snippetMatch *aMatch, /* Matching words */ + int nMatch, /* Number of entries in aMatch[] */ + int iCol /* The column number for zDoc[] */ +){ + int i; + if( iBreak<=10 ){ + return 0; + } + if( iBreak>=nDoc-10 ){ + return nDoc; + } + for(i=0; i0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ + return aMatch[i-1].iStart; + } + } + for(i=1; i<=10; i++){ + if( safe_isspace(zDoc[iBreak-i]) ){ + return iBreak - i + 1; + } + if( safe_isspace(zDoc[iBreak+i]) ){ + return iBreak + i + 1; + } + } + return iBreak; +} + + + +/* +** Allowed values for Snippet.aMatch[].snStatus +*/ +#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */ +#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */ + +/* +** Generate the text of a snippet. +*/ +static void snippetText( + fulltext_cursor *pCursor, /* The cursor we need the snippet for */ + const char *zStartMark, /* Markup to appear before each match */ + const char *zEndMark, /* Markup to appear after each match */ + const char *zEllipsis /* Ellipsis mark */ +){ + int i, j; + struct snippetMatch *aMatch; + int nMatch; + int nDesired; + StringBuffer sb; + int tailCol; + int tailOffset; + int iCol; + int nDoc; + const char *zDoc; + int iStart, iEnd; + int tailEllipsis = 0; + int iMatch; + + + free(pCursor->snippet.zSnippet); + pCursor->snippet.zSnippet = 0; + aMatch = pCursor->snippet.aMatch; + nMatch = pCursor->snippet.nMatch; + initStringBuffer(&sb); + + for(i=0; iq.nTerms; i++){ + for(j=0; j0; i++){ + if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue; + nDesired--; + iCol = aMatch[i].iCol; + zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1); + nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1); + iStart = aMatch[i].iStart - 40; + iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol); + if( iStart<=10 ){ + iStart = 0; + } + if( iCol==tailCol && iStart<=tailOffset+20 ){ + iStart = tailOffset; + } + if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ + trimWhiteSpace(&sb); + appendWhiteSpace(&sb); + append(&sb, zEllipsis); + appendWhiteSpace(&sb); + } + iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; + iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); + if( iEnd>=nDoc-10 ){ + iEnd = nDoc; + tailEllipsis = 0; + }else{ + tailEllipsis = 1; + } + while( iMatchsnippet.zSnippet = stringBufferData(&sb); + pCursor->snippet.nSnippet = stringBufferLength(&sb); +} + + +/* +** Close the cursor. For additional information see the documentation +** on the xClose method of the virtual table interface. +*/ +static int fulltextClose(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + TRACE(("FTS2 Close %p\n", c)); + sqlite3_finalize(c->pStmt); + queryClear(&c->q); + snippetClear(&c->snippet); + if( c->result.nData!=0 ) dlrDestroy(&c->reader); + dataBufferDestroy(&c->result); + free(c); + return SQLITE_OK; +} + +static int fulltextNext(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + int rc; + + TRACE(("FTS2 Next %p\n", pCursor)); + snippetClear(&c->snippet); + if( c->iCursorType < QUERY_FULLTEXT ){ + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + switch( rc ){ + case SQLITE_ROW: + c->eof = 0; + return SQLITE_OK; + case SQLITE_DONE: + c->eof = 1; + return SQLITE_OK; + default: + c->eof = 1; + return rc; + } + } else { /* full-text query */ + rc = sqlite3_reset(c->pStmt); + if( rc!=SQLITE_OK ) return rc; + + if( c->result.nData==0 || dlrAtEnd(&c->reader) ){ + c->eof = 1; + return SQLITE_OK; + } + rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader)); + dlrStep(&c->reader); + if( rc!=SQLITE_OK ) return rc; + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + if( rc==SQLITE_ROW ){ /* the case we expect */ + c->eof = 0; + return SQLITE_OK; + } + /* an error occurred; abort */ + return rc==SQLITE_DONE ? SQLITE_ERROR : rc; + } +} + + +/* TODO(shess) If we pushed LeafReader to the top of the file, or to +** another file, term_select() could be pushed above +** docListOfTerm(). +*/ +static int termSelect(fulltext_vtab *v, int iColumn, + const char *pTerm, int nTerm, int isPrefix, + DocListType iType, DataBuffer *out); + +/* Return a DocList corresponding to the query term *pTerm. If *pTerm +** is the first term of a phrase query, go ahead and evaluate the phrase +** query and return the doclist for the entire phrase query. +** +** The resulting DL_DOCIDS doclist is stored in pResult, which is +** overwritten. +*/ +static int docListOfTerm( + fulltext_vtab *v, /* The full text index */ + int iColumn, /* column to restrict to. No restriction if >=nColumn */ + QueryTerm *pQTerm, /* Term we are looking for, or 1st term of a phrase */ + DataBuffer *pResult /* Write the result here */ +){ + DataBuffer left, right, new; + int i, rc; + + /* No phrase search if no position info. */ + assert( pQTerm->nPhrase==0 || DL_DEFAULT!=DL_DOCIDS ); + + /* This code should never be called with buffered updates. */ + assert( v->nPendingData<0 ); + + dataBufferInit(&left, 0); + rc = termSelect(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pQTerm->isPrefix, + 0nPhrase ? DL_POSITIONS : DL_DOCIDS, &left); + if( rc ) return rc; + for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){ + dataBufferInit(&right, 0); + rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, + pQTerm[i].isPrefix, DL_POSITIONS, &right); + if( rc ){ + dataBufferDestroy(&left); + return rc; + } + dataBufferInit(&new, 0); + docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, + inPhrase ? DL_POSITIONS : DL_DOCIDS, &new); + dataBufferDestroy(&left); + dataBufferDestroy(&right); + left = new; + } + *pResult = left; + return SQLITE_OK; +} + +/* Add a new term pTerm[0..nTerm-1] to the query *q. +*/ +static void queryAdd(Query *q, const char *pTerm, int nTerm){ + QueryTerm *t; + ++q->nTerms; + q->pTerms = realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0])); + if( q->pTerms==0 ){ + q->nTerms = 0; + return; + } + t = &q->pTerms[q->nTerms - 1]; + CLEAR(t); + t->pTerm = malloc(nTerm+1); + memcpy(t->pTerm, pTerm, nTerm); + t->pTerm[nTerm] = 0; + t->nTerm = nTerm; + t->isOr = q->nextIsOr; + t->isPrefix = 0; + q->nextIsOr = 0; + t->iColumn = q->nextColumn; + q->nextColumn = q->dfltColumn; +} + +/* +** Check to see if the string zToken[0...nToken-1] matches any +** column name in the virtual table. If it does, +** return the zero-indexed column number. If not, return -1. +*/ +static int checkColumnSpecifier( + fulltext_vtab *pVtab, /* The virtual table */ + const char *zToken, /* Text of the token */ + int nToken /* Number of characters in the token */ +){ + int i; + for(i=0; inColumn; i++){ + if( memcmp(pVtab->azColumn[i], zToken, nToken)==0 + && pVtab->azColumn[i][nToken]==0 ){ + return i; + } + } + return -1; +} + +/* +** Parse the text at pSegment[0..nSegment-1]. Add additional terms +** to the query being assemblied in pQuery. +** +** inPhrase is true if pSegment[0..nSegement-1] is contained within +** double-quotes. If inPhrase is true, then the first term +** is marked with the number of terms in the phrase less one and +** OR and "-" syntax is ignored. If inPhrase is false, then every +** term found is marked with nPhrase=0 and OR and "-" syntax is significant. +*/ +static int tokenizeSegment( + sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */ + const char *pSegment, int nSegment, /* Query expression being parsed */ + int inPhrase, /* True if within "..." */ + Query *pQuery /* Append results here */ +){ + const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; + sqlite3_tokenizer_cursor *pCursor; + int firstIndex = pQuery->nTerms; + int iCol; + int nTerm = 1; + + int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); + if( rc!=SQLITE_OK ) return rc; + pCursor->pTokenizer = pTokenizer; + + while( 1 ){ + const char *pToken; + int nToken, iBegin, iEnd, iPos; + + rc = pModule->xNext(pCursor, + &pToken, &nToken, + &iBegin, &iEnd, &iPos); + if( rc!=SQLITE_OK ) break; + if( !inPhrase && + pSegment[iEnd]==':' && + (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ + pQuery->nextColumn = iCol; + continue; + } + if( !inPhrase && pQuery->nTerms>0 && nToken==2 + && pSegment[iBegin]=='O' && pSegment[iBegin+1]=='R' ){ + pQuery->nextIsOr = 1; + continue; + } + queryAdd(pQuery, pToken, nToken); + if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ + pQuery->pTerms[pQuery->nTerms-1].isNot = 1; + } + if( iEndpTerms[pQuery->nTerms-1].isPrefix = 1; + } + pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm; + if( inPhrase ){ + nTerm++; + } + } + + if( inPhrase && pQuery->nTerms>firstIndex ){ + pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1; + } + + return pModule->xClose(pCursor); +} + +/* Parse a query string, yielding a Query object pQuery. +** +** The calling function will need to queryClear() to clean up +** the dynamically allocated memory held by pQuery. +*/ +static int parseQuery( + fulltext_vtab *v, /* The fulltext index */ + const char *zInput, /* Input text of the query string */ + int nInput, /* Size of the input text */ + int dfltColumn, /* Default column of the index to match against */ + Query *pQuery /* Write the parse results here. */ +){ + int iInput, inPhrase = 0; + + if( zInput==0 ) nInput = 0; + if( nInput<0 ) nInput = strlen(zInput); + pQuery->nTerms = 0; + pQuery->pTerms = NULL; + pQuery->nextIsOr = 0; + pQuery->nextColumn = dfltColumn; + pQuery->dfltColumn = dfltColumn; + pQuery->pFts = v; + + for(iInput=0; iInputiInput ){ + tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase, + pQuery); + } + iInput = i; + if( i=nColumn +** they are allowed to match against any column. +*/ +static int fulltextQuery( + fulltext_vtab *v, /* The full text index */ + int iColumn, /* Match against this column by default */ + const char *zInput, /* The query string */ + int nInput, /* Number of bytes in zInput[] */ + DataBuffer *pResult, /* Write the result doclist here */ + Query *pQuery /* Put parsed query string here */ +){ + int i, iNext, rc; + DataBuffer left, right, or, new; + int nNot = 0; + QueryTerm *aTerm; + + /* TODO(shess) Instead of flushing pendingTerms, we could query for + ** the relevant term and merge the doclist into what we receive from + ** the database. Wait and see if this is a common issue, first. + ** + ** A good reason not to flush is to not generate update-related + ** error codes from here. + */ + + /* Flush any buffered updates before executing the query. */ + rc = flushPendingTerms(v); + if( rc!=SQLITE_OK ) return rc; + + /* TODO(shess) I think that the queryClear() calls below are not + ** necessary, because fulltextClose() already clears the query. + */ + rc = parseQuery(v, zInput, nInput, iColumn, pQuery); + if( rc!=SQLITE_OK ) return rc; + + /* Empty or NULL queries return no results. */ + if( pQuery->nTerms==0 ){ + dataBufferInit(pResult, 0); + return SQLITE_OK; + } + + /* Merge AND terms. */ + /* TODO(shess) I think we can early-exit if( i>nNot && left.nData==0 ). */ + aTerm = pQuery->pTerms; + for(i = 0; inTerms; i=iNext){ + if( aTerm[i].isNot ){ + /* Handle all NOT terms in a separate pass */ + nNot++; + iNext = i + aTerm[i].nPhrase+1; + continue; + } + iNext = i + aTerm[i].nPhrase + 1; + rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); + if( rc ){ + if( i!=nNot ) dataBufferDestroy(&left); + queryClear(pQuery); + return rc; + } + while( iNextnTerms && aTerm[iNext].isOr ){ + rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or); + iNext += aTerm[iNext].nPhrase + 1; + if( rc ){ + if( i!=nNot ) dataBufferDestroy(&left); + dataBufferDestroy(&right); + queryClear(pQuery); + return rc; + } + dataBufferInit(&new, 0); + docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); + dataBufferDestroy(&right); + dataBufferDestroy(&or); + right = new; + } + if( i==nNot ){ /* first term processed. */ + left = right; + }else{ + dataBufferInit(&new, 0); + docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new); + dataBufferDestroy(&right); + dataBufferDestroy(&left); + left = new; + } + } + + if( nNot==pQuery->nTerms ){ + /* We do not yet know how to handle a query of only NOT terms */ + return SQLITE_ERROR; + } + + /* Do the EXCEPT terms */ + for(i=0; inTerms; i += aTerm[i].nPhrase + 1){ + if( !aTerm[i].isNot ) continue; + rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); + if( rc ){ + queryClear(pQuery); + dataBufferDestroy(&left); + return rc; + } + dataBufferInit(&new, 0); + docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new); + dataBufferDestroy(&right); + dataBufferDestroy(&left); + left = new; + } + + *pResult = left; + return rc; +} + +/* +** This is the xFilter interface for the virtual table. See +** the virtual table xFilter method documentation for additional +** information. +** +** If idxNum==QUERY_GENERIC then do a full table scan against +** the %_content table. +** +** If idxNum==QUERY_ROWID then do a rowid lookup for a single entry +** in the %_content table. +** +** If idxNum>=QUERY_FULLTEXT then use the full text index. The +** column on the left-hand side of the MATCH operator is column +** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand +** side of the MATCH operator. +*/ +/* TODO(shess) Upgrade the cursor initialization and destruction to +** account for fulltextFilter() being called multiple times on the +** same cursor. The current solution is very fragile. Apply fix to +** fts2 as appropriate. +*/ +static int fulltextFilter( + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ + int idxNum, const char *idxStr, /* Which indexing scheme to use */ + int argc, sqlite3_value **argv /* Arguments for the indexing scheme */ +){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + fulltext_vtab *v = cursor_vtab(c); + int rc; + char *zSql; + + TRACE(("FTS2 Filter %p\n",pCursor)); + + zSql = sqlite3_mprintf("select rowid, * from %%_content %s", + idxNum==QUERY_GENERIC ? "" : "where rowid=?"); + sqlite3_finalize(c->pStmt); + rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, zSql); + sqlite3_free(zSql); + if( rc!=SQLITE_OK ) return rc; + + c->iCursorType = idxNum; + switch( idxNum ){ + case QUERY_GENERIC: + break; + + case QUERY_ROWID: + rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0])); + if( rc!=SQLITE_OK ) return rc; + break; + + default: /* full-text search */ + { + const char *zQuery = (const char *)sqlite3_value_text(argv[0]); + assert( idxNum<=QUERY_FULLTEXT+v->nColumn); + assert( argc==1 ); + queryClear(&c->q); + if( c->result.nData!=0 ){ + /* This case happens if the same cursor is used repeatedly. */ + dlrDestroy(&c->reader); + dataBufferReset(&c->result); + }else{ + dataBufferInit(&c->result, 0); + } + rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q); + if( rc!=SQLITE_OK ) return rc; + if( c->result.nData!=0 ){ + dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); + } + break; + } + } + + return fulltextNext(pCursor); +} + +/* This is the xEof method of the virtual table. The SQLite core +** calls this routine to find out if it has reached the end of +** a query's results set. +*/ +static int fulltextEof(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + return c->eof; +} + +/* This is the xColumn method of the virtual table. The SQLite +** core calls this method during a query when it needs the value +** of a column from the virtual table. This method needs to use +** one of the sqlite3_result_*() routines to store the requested +** value back in the pContext. +*/ +static int fulltextColumn(sqlite3_vtab_cursor *pCursor, + sqlite3_context *pContext, int idxCol){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + fulltext_vtab *v = cursor_vtab(c); + + if( idxColnColumn ){ + sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); + sqlite3_result_value(pContext, pVal); + }else if( idxCol==v->nColumn ){ + /* The extra column whose name is the same as the table. + ** Return a blob which is a pointer to the cursor + */ + sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); + } + return SQLITE_OK; +} + +/* This is the xRowid method. The SQLite core calls this routine to +** retrive the rowid for the current row of the result set. The +** rowid should be written to *pRowid. +*/ +static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + + *pRowid = sqlite3_column_int64(c->pStmt, 0); + return SQLITE_OK; +} + +/* Add all terms in [zText] to pendingTerms table. If [iColumn] > 0, +** we also store positions and offsets in the hash table using that +** column number. +*/ +static int buildTerms(fulltext_vtab *v, sqlite_int64 iDocid, + const char *zText, int iColumn){ + sqlite3_tokenizer *pTokenizer = v->pTokenizer; + sqlite3_tokenizer_cursor *pCursor; + const char *pToken; + int nTokenBytes; + int iStartOffset, iEndOffset, iPosition; + int rc; + + rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor); + if( rc!=SQLITE_OK ) return rc; + + pCursor->pTokenizer = pTokenizer; + while( SQLITE_OK==pTokenizer->pModule->xNext(pCursor, + &pToken, &nTokenBytes, + &iStartOffset, &iEndOffset, + &iPosition) ){ + DLCollector *p; + int nData; /* Size of doclist before our update. */ + + /* Positions can't be negative; we use -1 as a terminator internally. */ + if( iPosition<0 ){ + pTokenizer->pModule->xClose(pCursor); + return SQLITE_ERROR; + } + + p = fts2HashFind(&v->pendingTerms, pToken, nTokenBytes); + if( p==NULL ){ + nData = 0; + p = dlcNew(iDocid, DL_DEFAULT); + fts2HashInsert(&v->pendingTerms, pToken, nTokenBytes, p); + + /* Overhead for our hash table entry, the key, and the value. */ + v->nPendingData += sizeof(struct fts2HashElem)+sizeof(*p)+nTokenBytes; + }else{ + nData = p->b.nData; + if( p->dlw.iPrevDocid!=iDocid ) dlcNext(p, iDocid); + } + if( iColumn>=0 ){ + dlcAddPos(p, iColumn, iPosition, iStartOffset, iEndOffset); + } + + /* Accumulate data added by dlcNew or dlcNext, and dlcAddPos. */ + v->nPendingData += p->b.nData-nData; + } + + /* TODO(shess) Check return? Should this be able to cause errors at + ** this point? Actually, same question about sqlite3_finalize(), + ** though one could argue that failure there means that the data is + ** not durable. *ponder* + */ + pTokenizer->pModule->xClose(pCursor); + return rc; +} + +/* Add doclists for all terms in [pValues] to pendingTerms table. */ +static int insertTerms(fulltext_vtab *v, sqlite_int64 iRowid, + sqlite3_value **pValues){ + int i; + for(i = 0; i < v->nColumn ; ++i){ + char *zText = (char*)sqlite3_value_text(pValues[i]); + int rc = buildTerms(v, iRowid, zText, i); + if( rc!=SQLITE_OK ) return rc; + } + return SQLITE_OK; +} + +/* Add empty doclists for all terms in the given row's content to +** pendingTerms. +*/ +static int deleteTerms(fulltext_vtab *v, sqlite_int64 iRowid){ + const char **pValues; + int i, rc; + + /* TODO(shess) Should we allow such tables at all? */ + if( DL_DEFAULT==DL_DOCIDS ) return SQLITE_ERROR; + + rc = content_select(v, iRowid, &pValues); + if( rc!=SQLITE_OK ) return rc; + + for(i = 0 ; i < v->nColumn; ++i) { + rc = buildTerms(v, iRowid, pValues[i], -1); + if( rc!=SQLITE_OK ) break; + } + + freeStringArray(v->nColumn, pValues); + return SQLITE_OK; +} + +/* TODO(shess) Refactor the code to remove this forward decl. */ +static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid); + +/* Insert a row into the %_content table; set *piRowid to be the ID of the +** new row. Add doclists for terms to pendingTerms. +*/ +static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestRowid, + sqlite3_value **pValues, sqlite_int64 *piRowid){ + int rc; + + rc = content_insert(v, pRequestRowid, pValues); /* execute an SQL INSERT */ + if( rc!=SQLITE_OK ) return rc; + + *piRowid = sqlite3_last_insert_rowid(v->db); + rc = initPendingTerms(v, *piRowid); + if( rc!=SQLITE_OK ) return rc; + + return insertTerms(v, *piRowid, pValues); +} + +/* Delete a row from the %_content table; add empty doclists for terms +** to pendingTerms. +*/ +static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ + int rc = initPendingTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = deleteTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + return content_delete(v, iRow); /* execute an SQL DELETE */ +} + +/* Update a row in the %_content table; add delete doclists to +** pendingTerms for old terms not in the new data, add insert doclists +** to pendingTerms for terms in the new data. +*/ +static int index_update(fulltext_vtab *v, sqlite_int64 iRow, + sqlite3_value **pValues){ + int rc = initPendingTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + /* Generate an empty doclist for each term that previously appeared in this + * row. */ + rc = deleteTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = content_update(v, pValues, iRow); /* execute an SQL UPDATE */ + if( rc!=SQLITE_OK ) return rc; + + /* Now add positions for terms which appear in the updated row. */ + return insertTerms(v, iRow, pValues); +} + +/*******************************************************************/ +/* InteriorWriter is used to collect terms and block references into +** interior nodes in %_segments. See commentary at top of file for +** format. +*/ + +/* How large interior nodes can grow. */ +#define INTERIOR_MAX 2048 + +/* Minimum number of terms per interior node (except the root). This +** prevents large terms from making the tree too skinny - must be >0 +** so that the tree always makes progress. Note that the min tree +** fanout will be INTERIOR_MIN_TERMS+1. +*/ +#define INTERIOR_MIN_TERMS 7 +#if INTERIOR_MIN_TERMS<1 +# error INTERIOR_MIN_TERMS must be greater than 0. +#endif + +/* ROOT_MAX controls how much data is stored inline in the segment +** directory. +*/ +/* TODO(shess) Push ROOT_MAX down to whoever is writing things. It's +** only here so that interiorWriterRootInfo() and leafWriterRootInfo() +** can both see it, but if the caller passed it in, we wouldn't even +** need a define. +*/ +#define ROOT_MAX 1024 +#if ROOT_MAXterm, 0); + dataBufferReplace(&block->term, pTerm, nTerm); + + n = putVarint(c, iHeight); + n += putVarint(c+n, iChildBlock); + dataBufferInit(&block->data, INTERIOR_MAX); + dataBufferReplace(&block->data, c, n); + + return block; +} + +#ifndef NDEBUG +/* Verify that the data is readable as an interior node. */ +static void interiorBlockValidate(InteriorBlock *pBlock){ + const char *pData = pBlock->data.pData; + int nData = pBlock->data.nData; + int n, iDummy; + sqlite_int64 iBlockid; + + assert( nData>0 ); + assert( pData!=0 ); + assert( pData+nData>pData ); + + /* Must lead with height of node as a varint(n), n>0 */ + n = getVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>0 ); + assert( n0 ); + assert( n<=nData ); + pData += n; + nData -= n; + + /* Zero or more terms of positive length */ + if( nData!=0 ){ + /* First term is not delta-encoded. */ + n = getVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>0 ); + assert( n+iDummy>0); + assert( n+iDummy<=nData ); + pData += n+iDummy; + nData -= n+iDummy; + + /* Following terms delta-encoded. */ + while( nData!=0 ){ + /* Length of shared prefix. */ + n = getVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>=0 ); + assert( n0 ); + assert( iDummy>0 ); + assert( n+iDummy>0); + assert( n+iDummy<=nData ); + pData += n+iDummy; + nData -= n+iDummy; + } + } +} +#define ASSERT_VALID_INTERIOR_BLOCK(x) interiorBlockValidate(x) +#else +#define ASSERT_VALID_INTERIOR_BLOCK(x) assert( 1 ) +#endif + +typedef struct InteriorWriter { + int iHeight; /* from 0 at leaves. */ + InteriorBlock *first, *last; + struct InteriorWriter *parentWriter; + + DataBuffer term; /* Last term written to block "last". */ + sqlite_int64 iOpeningChildBlock; /* First child block in block "last". */ +#ifndef NDEBUG + sqlite_int64 iLastChildBlock; /* for consistency checks. */ +#endif +} InteriorWriter; + +/* Initialize an interior node where pTerm[nTerm] marks the leftmost +** term in the tree. iChildBlock is the leftmost child block at the +** next level down the tree. +*/ +static void interiorWriterInit(int iHeight, const char *pTerm, int nTerm, + sqlite_int64 iChildBlock, + InteriorWriter *pWriter){ + InteriorBlock *block; + assert( iHeight>0 ); + CLEAR(pWriter); + + pWriter->iHeight = iHeight; + pWriter->iOpeningChildBlock = iChildBlock; +#ifndef NDEBUG + pWriter->iLastChildBlock = iChildBlock; +#endif + block = interiorBlockNew(iHeight, iChildBlock, pTerm, nTerm); + pWriter->last = pWriter->first = block; + ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); + dataBufferInit(&pWriter->term, 0); +} + +/* Append the child node rooted at iChildBlock to the interior node, +** with pTerm[nTerm] as the leftmost term in iChildBlock's subtree. +*/ +static void interiorWriterAppend(InteriorWriter *pWriter, + const char *pTerm, int nTerm, + sqlite_int64 iChildBlock){ + char c[VARINT_MAX+VARINT_MAX]; + int n, nPrefix = 0; + + ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); + + /* The first term written into an interior node is actually + ** associated with the second child added (the first child was added + ** in interiorWriterInit, or in the if clause at the bottom of this + ** function). That term gets encoded straight up, with nPrefix left + ** at 0. + */ + if( pWriter->term.nData==0 ){ + n = putVarint(c, nTerm); + }else{ + while( nPrefixterm.nData && + pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){ + nPrefix++; + } + + n = putVarint(c, nPrefix); + n += putVarint(c+n, nTerm-nPrefix); + } + +#ifndef NDEBUG + pWriter->iLastChildBlock++; +#endif + assert( pWriter->iLastChildBlock==iChildBlock ); + + /* Overflow to a new block if the new term makes the current block + ** too big, and the current block already has enough terms. + */ + if( pWriter->last->data.nData+n+nTerm-nPrefix>INTERIOR_MAX && + iChildBlock-pWriter->iOpeningChildBlock>INTERIOR_MIN_TERMS ){ + pWriter->last->next = interiorBlockNew(pWriter->iHeight, iChildBlock, + pTerm, nTerm); + pWriter->last = pWriter->last->next; + pWriter->iOpeningChildBlock = iChildBlock; + dataBufferReset(&pWriter->term); + }else{ + dataBufferAppend2(&pWriter->last->data, c, n, + pTerm+nPrefix, nTerm-nPrefix); + dataBufferReplace(&pWriter->term, pTerm, nTerm); + } + ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); +} + +/* Free the space used by pWriter, including the linked-list of +** InteriorBlocks, and parentWriter, if present. +*/ +static int interiorWriterDestroy(InteriorWriter *pWriter){ + InteriorBlock *block = pWriter->first; + + while( block!=NULL ){ + InteriorBlock *b = block; + block = block->next; + dataBufferDestroy(&b->term); + dataBufferDestroy(&b->data); + free(b); + } + if( pWriter->parentWriter!=NULL ){ + interiorWriterDestroy(pWriter->parentWriter); + free(pWriter->parentWriter); + } + dataBufferDestroy(&pWriter->term); + SCRAMBLE(pWriter); + return SQLITE_OK; +} + +/* If pWriter can fit entirely in ROOT_MAX, return it as the root info +** directly, leaving *piEndBlockid unchanged. Otherwise, flush +** pWriter to %_segments, building a new layer of interior nodes, and +** recursively ask for their root into. +*/ +static int interiorWriterRootInfo(fulltext_vtab *v, InteriorWriter *pWriter, + char **ppRootInfo, int *pnRootInfo, + sqlite_int64 *piEndBlockid){ + InteriorBlock *block = pWriter->first; + sqlite_int64 iBlockid = 0; + int rc; + + /* If we can fit the segment inline */ + if( block==pWriter->last && block->data.nDatadata.pData; + *pnRootInfo = block->data.nData; + return SQLITE_OK; + } + + /* Flush the first block to %_segments, and create a new level of + ** interior node. + */ + ASSERT_VALID_INTERIOR_BLOCK(block); + rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); + if( rc!=SQLITE_OK ) return rc; + *piEndBlockid = iBlockid; + + pWriter->parentWriter = malloc(sizeof(*pWriter->parentWriter)); + interiorWriterInit(pWriter->iHeight+1, + block->term.pData, block->term.nData, + iBlockid, pWriter->parentWriter); + + /* Flush additional blocks and append to the higher interior + ** node. + */ + for(block=block->next; block!=NULL; block=block->next){ + ASSERT_VALID_INTERIOR_BLOCK(block); + rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); + if( rc!=SQLITE_OK ) return rc; + *piEndBlockid = iBlockid; + + interiorWriterAppend(pWriter->parentWriter, + block->term.pData, block->term.nData, iBlockid); + } + + /* Parent node gets the chance to be the root. */ + return interiorWriterRootInfo(v, pWriter->parentWriter, + ppRootInfo, pnRootInfo, piEndBlockid); +} + +/****************************************************************/ +/* InteriorReader is used to read off the data from an interior node +** (see comment at top of file for the format). +*/ +typedef struct InteriorReader { + const char *pData; + int nData; + + DataBuffer term; /* previous term, for decoding term delta. */ + + sqlite_int64 iBlockid; +} InteriorReader; + +static void interiorReaderDestroy(InteriorReader *pReader){ + dataBufferDestroy(&pReader->term); + SCRAMBLE(pReader); +} + +/* TODO(shess) The assertions are great, but what if we're in NDEBUG +** and the blob is empty or otherwise contains suspect data? +*/ +static void interiorReaderInit(const char *pData, int nData, + InteriorReader *pReader){ + int n, nTerm; + + /* Require at least the leading flag byte */ + assert( nData>0 ); + assert( pData[0]!='\0' ); + + CLEAR(pReader); + + /* Decode the base blockid, and set the cursor to the first term. */ + n = getVarint(pData+1, &pReader->iBlockid); + assert( 1+n<=nData ); + pReader->pData = pData+1+n; + pReader->nData = nData-(1+n); + + /* A single-child interior node (such as when a leaf node was too + ** large for the segment directory) won't have any terms. + ** Otherwise, decode the first term. + */ + if( pReader->nData==0 ){ + dataBufferInit(&pReader->term, 0); + }else{ + n = getVarint32(pReader->pData, &nTerm); + dataBufferInit(&pReader->term, nTerm); + dataBufferReplace(&pReader->term, pReader->pData+n, nTerm); + assert( n+nTerm<=pReader->nData ); + pReader->pData += n+nTerm; + pReader->nData -= n+nTerm; + } +} + +static int interiorReaderAtEnd(InteriorReader *pReader){ + return pReader->term.nData==0; +} + +static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){ + return pReader->iBlockid; +} + +static int interiorReaderTermBytes(InteriorReader *pReader){ + assert( !interiorReaderAtEnd(pReader) ); + return pReader->term.nData; +} +static const char *interiorReaderTerm(InteriorReader *pReader){ + assert( !interiorReaderAtEnd(pReader) ); + return pReader->term.pData; +} + +/* Step forward to the next term in the node. */ +static void interiorReaderStep(InteriorReader *pReader){ + assert( !interiorReaderAtEnd(pReader) ); + + /* If the last term has been read, signal eof, else construct the + ** next term. + */ + if( pReader->nData==0 ){ + dataBufferReset(&pReader->term); + }else{ + int n, nPrefix, nSuffix; + + n = getVarint32(pReader->pData, &nPrefix); + n += getVarint32(pReader->pData+n, &nSuffix); + + /* Truncate the current term and append suffix data. */ + pReader->term.nData = nPrefix; + dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); + + assert( n+nSuffix<=pReader->nData ); + pReader->pData += n+nSuffix; + pReader->nData -= n+nSuffix; + } + pReader->iBlockid++; +} + +/* Compare the current term to pTerm[nTerm], returning strcmp-style +** results. If isPrefix, equality means equal through nTerm bytes. +*/ +static int interiorReaderTermCmp(InteriorReader *pReader, + const char *pTerm, int nTerm, int isPrefix){ + const char *pReaderTerm = interiorReaderTerm(pReader); + int nReaderTerm = interiorReaderTermBytes(pReader); + int c, n = nReaderTerm0 ) return -1; + if( nTerm>0 ) return 1; + return 0; + } + + c = memcmp(pReaderTerm, pTerm, n); + if( c!=0 ) return c; + if( isPrefix && n==nTerm ) return 0; + return nReaderTerm - nTerm; +} + +/****************************************************************/ +/* LeafWriter is used to collect terms and associated doclist data +** into leaf blocks in %_segments (see top of file for format info). +** Expected usage is: +** +** LeafWriter writer; +** leafWriterInit(0, 0, &writer); +** while( sorted_terms_left_to_process ){ +** // data is doclist data for that term. +** rc = leafWriterStep(v, &writer, pTerm, nTerm, pData, nData); +** if( rc!=SQLITE_OK ) goto err; +** } +** rc = leafWriterFinalize(v, &writer); +**err: +** leafWriterDestroy(&writer); +** return rc; +** +** leafWriterStep() may write a collected leaf out to %_segments. +** leafWriterFinalize() finishes writing any buffered data and stores +** a root node in %_segdir. leafWriterDestroy() frees all buffers and +** InteriorWriters allocated as part of writing this segment. +** +** TODO(shess) Document leafWriterStepMerge(). +*/ + +/* Put terms with data this big in their own block. */ +#define STANDALONE_MIN 1024 + +/* Keep leaf blocks below this size. */ +#define LEAF_MAX 2048 + +typedef struct LeafWriter { + int iLevel; + int idx; + sqlite_int64 iStartBlockid; /* needed to create the root info */ + sqlite_int64 iEndBlockid; /* when we're done writing. */ + + DataBuffer term; /* previous encoded term */ + DataBuffer data; /* encoding buffer */ + + /* bytes of first term in the current node which distinguishes that + ** term from the last term of the previous node. + */ + int nTermDistinct; + + InteriorWriter parentWriter; /* if we overflow */ + int has_parent; +} LeafWriter; + +static void leafWriterInit(int iLevel, int idx, LeafWriter *pWriter){ + CLEAR(pWriter); + pWriter->iLevel = iLevel; + pWriter->idx = idx; + + dataBufferInit(&pWriter->term, 32); + + /* Start out with a reasonably sized block, though it can grow. */ + dataBufferInit(&pWriter->data, LEAF_MAX); +} + +#ifndef NDEBUG +/* Verify that the data is readable as a leaf node. */ +static void leafNodeValidate(const char *pData, int nData){ + int n, iDummy; + + if( nData==0 ) return; + assert( nData>0 ); + assert( pData!=0 ); + assert( pData+nData>pData ); + + /* Must lead with a varint(0) */ + n = getVarint32(pData, &iDummy); + assert( iDummy==0 ); + assert( n>0 ); + assert( n0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy<=nData ); + ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL); + pData += n+iDummy; + nData -= n+iDummy; + + /* Verify that trailing terms and doclists also are readable. */ + while( nData!=0 ){ + n = getVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>=0 ); + assert( n0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy<=nData ); + ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL); + pData += n+iDummy; + nData -= n+iDummy; + } +} +#define ASSERT_VALID_LEAF_NODE(p, n) leafNodeValidate(p, n) +#else +#define ASSERT_VALID_LEAF_NODE(p, n) assert( 1 ) +#endif + +/* Flush the current leaf node to %_segments, and adding the resulting +** blockid and the starting term to the interior node which will +** contain it. +*/ +static int leafWriterInternalFlush(fulltext_vtab *v, LeafWriter *pWriter, + int iData, int nData){ + sqlite_int64 iBlockid = 0; + const char *pStartingTerm; + int nStartingTerm, rc, n; + + /* Must have the leading varint(0) flag, plus at least some + ** valid-looking data. + */ + assert( nData>2 ); + assert( iData>=0 ); + assert( iData+nData<=pWriter->data.nData ); + ASSERT_VALID_LEAF_NODE(pWriter->data.pData+iData, nData); + + rc = block_insert(v, pWriter->data.pData+iData, nData, &iBlockid); + if( rc!=SQLITE_OK ) return rc; + assert( iBlockid!=0 ); + + /* Reconstruct the first term in the leaf for purposes of building + ** the interior node. + */ + n = getVarint32(pWriter->data.pData+iData+1, &nStartingTerm); + pStartingTerm = pWriter->data.pData+iData+1+n; + assert( pWriter->data.nData>iData+1+n+nStartingTerm ); + assert( pWriter->nTermDistinct>0 ); + assert( pWriter->nTermDistinct<=nStartingTerm ); + nStartingTerm = pWriter->nTermDistinct; + + if( pWriter->has_parent ){ + interiorWriterAppend(&pWriter->parentWriter, + pStartingTerm, nStartingTerm, iBlockid); + }else{ + interiorWriterInit(1, pStartingTerm, nStartingTerm, iBlockid, + &pWriter->parentWriter); + pWriter->has_parent = 1; + } + + /* Track the span of this segment's leaf nodes. */ + if( pWriter->iEndBlockid==0 ){ + pWriter->iEndBlockid = pWriter->iStartBlockid = iBlockid; + }else{ + pWriter->iEndBlockid++; + assert( iBlockid==pWriter->iEndBlockid ); + } + + return SQLITE_OK; +} +static int leafWriterFlush(fulltext_vtab *v, LeafWriter *pWriter){ + int rc = leafWriterInternalFlush(v, pWriter, 0, pWriter->data.nData); + if( rc!=SQLITE_OK ) return rc; + + /* Re-initialize the output buffer. */ + dataBufferReset(&pWriter->data); + + return SQLITE_OK; +} + +/* Fetch the root info for the segment. If the entire leaf fits +** within ROOT_MAX, then it will be returned directly, otherwise it +** will be flushed and the root info will be returned from the +** interior node. *piEndBlockid is set to the blockid of the last +** interior or leaf node written to disk (0 if none are written at +** all). +*/ +static int leafWriterRootInfo(fulltext_vtab *v, LeafWriter *pWriter, + char **ppRootInfo, int *pnRootInfo, + sqlite_int64 *piEndBlockid){ + /* we can fit the segment entirely inline */ + if( !pWriter->has_parent && pWriter->data.nDatadata.pData; + *pnRootInfo = pWriter->data.nData; + *piEndBlockid = 0; + return SQLITE_OK; + } + + /* Flush remaining leaf data. */ + if( pWriter->data.nData>0 ){ + int rc = leafWriterFlush(v, pWriter); + if( rc!=SQLITE_OK ) return rc; + } + + /* We must have flushed a leaf at some point. */ + assert( pWriter->has_parent ); + + /* Tenatively set the end leaf blockid as the end blockid. If the + ** interior node can be returned inline, this will be the final + ** blockid, otherwise it will be overwritten by + ** interiorWriterRootInfo(). + */ + *piEndBlockid = pWriter->iEndBlockid; + + return interiorWriterRootInfo(v, &pWriter->parentWriter, + ppRootInfo, pnRootInfo, piEndBlockid); +} + +/* Collect the rootInfo data and store it into the segment directory. +** This has the effect of flushing the segment's leaf data to +** %_segments, and also flushing any interior nodes to %_segments. +*/ +static int leafWriterFinalize(fulltext_vtab *v, LeafWriter *pWriter){ + sqlite_int64 iEndBlockid; + char *pRootInfo; + int rc, nRootInfo; + + rc = leafWriterRootInfo(v, pWriter, &pRootInfo, &nRootInfo, &iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + /* Don't bother storing an entirely empty segment. */ + if( iEndBlockid==0 && nRootInfo==0 ) return SQLITE_OK; + + return segdir_set(v, pWriter->iLevel, pWriter->idx, + pWriter->iStartBlockid, pWriter->iEndBlockid, + iEndBlockid, pRootInfo, nRootInfo); +} + +static void leafWriterDestroy(LeafWriter *pWriter){ + if( pWriter->has_parent ) interiorWriterDestroy(&pWriter->parentWriter); + dataBufferDestroy(&pWriter->term); + dataBufferDestroy(&pWriter->data); +} + +/* Encode a term into the leafWriter, delta-encoding as appropriate. +** Returns the length of the new term which distinguishes it from the +** previous term, which can be used to set nTermDistinct when a node +** boundary is crossed. +*/ +static int leafWriterEncodeTerm(LeafWriter *pWriter, + const char *pTerm, int nTerm){ + char c[VARINT_MAX+VARINT_MAX]; + int n, nPrefix = 0; + + assert( nTerm>0 ); + while( nPrefixterm.nData && + pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){ + nPrefix++; + /* Failing this implies that the terms weren't in order. */ + assert( nPrefixdata.nData==0 ){ + /* Encode the node header and leading term as: + ** varint(0) + ** varint(nTerm) + ** char pTerm[nTerm] + */ + n = putVarint(c, '\0'); + n += putVarint(c+n, nTerm); + dataBufferAppend2(&pWriter->data, c, n, pTerm, nTerm); + }else{ + /* Delta-encode the term as: + ** varint(nPrefix) + ** varint(nSuffix) + ** char pTermSuffix[nSuffix] + */ + n = putVarint(c, nPrefix); + n += putVarint(c+n, nTerm-nPrefix); + dataBufferAppend2(&pWriter->data, c, n, pTerm+nPrefix, nTerm-nPrefix); + } + dataBufferReplace(&pWriter->term, pTerm, nTerm); + + return nPrefix+1; +} + +/* Used to avoid a memmove when a large amount of doclist data is in +** the buffer. This constructs a node and term header before +** iDoclistData and flushes the resulting complete node using +** leafWriterInternalFlush(). +*/ +static int leafWriterInlineFlush(fulltext_vtab *v, LeafWriter *pWriter, + const char *pTerm, int nTerm, + int iDoclistData){ + char c[VARINT_MAX+VARINT_MAX]; + int iData, n = putVarint(c, 0); + n += putVarint(c+n, nTerm); + + /* There should always be room for the header. Even if pTerm shared + ** a substantial prefix with the previous term, the entire prefix + ** could be constructed from earlier data in the doclist, so there + ** should be room. + */ + assert( iDoclistData>=n+nTerm ); + + iData = iDoclistData-(n+nTerm); + memcpy(pWriter->data.pData+iData, c, n); + memcpy(pWriter->data.pData+iData+n, pTerm, nTerm); + + return leafWriterInternalFlush(v, pWriter, iData, pWriter->data.nData-iData); +} + +/* Push pTerm[nTerm] along with the doclist data to the leaf layer of +** %_segments. +*/ +static int leafWriterStepMerge(fulltext_vtab *v, LeafWriter *pWriter, + const char *pTerm, int nTerm, + DLReader *pReaders, int nReaders){ + char c[VARINT_MAX+VARINT_MAX]; + int iTermData = pWriter->data.nData, iDoclistData; + int i, nData, n, nActualData, nActual, rc, nTermDistinct; + + ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData); + nTermDistinct = leafWriterEncodeTerm(pWriter, pTerm, nTerm); + + /* Remember nTermDistinct if opening a new node. */ + if( iTermData==0 ) pWriter->nTermDistinct = nTermDistinct; + + iDoclistData = pWriter->data.nData; + + /* Estimate the length of the merged doclist so we can leave space + ** to encode it. + */ + for(i=0, nData=0; idata, c, n); + + docListMerge(&pWriter->data, pReaders, nReaders); + ASSERT_VALID_DOCLIST(DL_DEFAULT, + pWriter->data.pData+iDoclistData+n, + pWriter->data.nData-iDoclistData-n, NULL); + + /* The actual amount of doclist data at this point could be smaller + ** than the length we encoded. Additionally, the space required to + ** encode this length could be smaller. For small doclists, this is + ** not a big deal, we can just use memmove() to adjust things. + */ + nActualData = pWriter->data.nData-(iDoclistData+n); + nActual = putVarint(c, nActualData); + assert( nActualData<=nData ); + assert( nActual<=n ); + + /* If the new doclist is big enough for force a standalone leaf + ** node, we can immediately flush it inline without doing the + ** memmove(). + */ + /* TODO(shess) This test matches leafWriterStep(), which does this + ** test before it knows the cost to varint-encode the term and + ** doclist lengths. At some point, change to + ** pWriter->data.nData-iTermData>STANDALONE_MIN. + */ + if( nTerm+nActualData>STANDALONE_MIN ){ + /* Push leaf node from before this term. */ + if( iTermData>0 ){ + rc = leafWriterInternalFlush(v, pWriter, 0, iTermData); + if( rc!=SQLITE_OK ) return rc; + + pWriter->nTermDistinct = nTermDistinct; + } + + /* Fix the encoded doclist length. */ + iDoclistData += n - nActual; + memcpy(pWriter->data.pData+iDoclistData, c, nActual); + + /* Push the standalone leaf node. */ + rc = leafWriterInlineFlush(v, pWriter, pTerm, nTerm, iDoclistData); + if( rc!=SQLITE_OK ) return rc; + + /* Leave the node empty. */ + dataBufferReset(&pWriter->data); + + return rc; + } + + /* At this point, we know that the doclist was small, so do the + ** memmove if indicated. + */ + if( nActualdata.pData+iDoclistData+nActual, + pWriter->data.pData+iDoclistData+n, + pWriter->data.nData-(iDoclistData+n)); + pWriter->data.nData -= n-nActual; + } + + /* Replace written length with actual length. */ + memcpy(pWriter->data.pData+iDoclistData, c, nActual); + + /* If the node is too large, break things up. */ + /* TODO(shess) This test matches leafWriterStep(), which does this + ** test before it knows the cost to varint-encode the term and + ** doclist lengths. At some point, change to + ** pWriter->data.nData>LEAF_MAX. + */ + if( iTermData+nTerm+nActualData>LEAF_MAX ){ + /* Flush out the leading data as a node */ + rc = leafWriterInternalFlush(v, pWriter, 0, iTermData); + if( rc!=SQLITE_OK ) return rc; + + pWriter->nTermDistinct = nTermDistinct; + + /* Rebuild header using the current term */ + n = putVarint(pWriter->data.pData, 0); + n += putVarint(pWriter->data.pData+n, nTerm); + memcpy(pWriter->data.pData+n, pTerm, nTerm); + n += nTerm; + + /* There should always be room, because the previous encoding + ** included all data necessary to construct the term. + */ + assert( ndata.nData-iDoclistDatadata.pData+n, + pWriter->data.pData+iDoclistData, + pWriter->data.nData-iDoclistData); + pWriter->data.nData -= iDoclistData-n; + } + ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData); + + return SQLITE_OK; +} + +/* Push pTerm[nTerm] along with the doclist data to the leaf layer of +** %_segments. +*/ +/* TODO(shess) Revise writeZeroSegment() so that doclists are +** constructed directly in pWriter->data. +*/ +static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter, + const char *pTerm, int nTerm, + const char *pData, int nData){ + int rc; + DLReader reader; + + dlrInit(&reader, DL_DEFAULT, pData, nData); + rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1); + dlrDestroy(&reader); + + return rc; +} + + +/****************************************************************/ +/* LeafReader is used to iterate over an individual leaf node. */ +typedef struct LeafReader { + DataBuffer term; /* copy of current term. */ + + const char *pData; /* data for current term. */ + int nData; +} LeafReader; + +static void leafReaderDestroy(LeafReader *pReader){ + dataBufferDestroy(&pReader->term); + SCRAMBLE(pReader); +} + +static int leafReaderAtEnd(LeafReader *pReader){ + return pReader->nData<=0; +} + +/* Access the current term. */ +static int leafReaderTermBytes(LeafReader *pReader){ + return pReader->term.nData; +} +static const char *leafReaderTerm(LeafReader *pReader){ + assert( pReader->term.nData>0 ); + return pReader->term.pData; +} + +/* Access the doclist data for the current term. */ +static int leafReaderDataBytes(LeafReader *pReader){ + int nData; + assert( pReader->term.nData>0 ); + getVarint32(pReader->pData, &nData); + return nData; +} +static const char *leafReaderData(LeafReader *pReader){ + int n, nData; + assert( pReader->term.nData>0 ); + n = getVarint32(pReader->pData, &nData); + return pReader->pData+n; +} + +static void leafReaderInit(const char *pData, int nData, + LeafReader *pReader){ + int nTerm, n; + + assert( nData>0 ); + assert( pData[0]=='\0' ); + + CLEAR(pReader); + + /* Read the first term, skipping the header byte. */ + n = getVarint32(pData+1, &nTerm); + dataBufferInit(&pReader->term, nTerm); + dataBufferReplace(&pReader->term, pData+1+n, nTerm); + + /* Position after the first term. */ + assert( 1+n+nTermpData = pData+1+n+nTerm; + pReader->nData = nData-1-n-nTerm; +} + +/* Step the reader forward to the next term. */ +static void leafReaderStep(LeafReader *pReader){ + int n, nData, nPrefix, nSuffix; + assert( !leafReaderAtEnd(pReader) ); + + /* Skip previous entry's data block. */ + n = getVarint32(pReader->pData, &nData); + assert( n+nData<=pReader->nData ); + pReader->pData += n+nData; + pReader->nData -= n+nData; + + if( !leafReaderAtEnd(pReader) ){ + /* Construct the new term using a prefix from the old term plus a + ** suffix from the leaf data. + */ + n = getVarint32(pReader->pData, &nPrefix); + n += getVarint32(pReader->pData+n, &nSuffix); + assert( n+nSuffixnData ); + pReader->term.nData = nPrefix; + dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); + + pReader->pData += n+nSuffix; + pReader->nData -= n+nSuffix; + } +} + +/* strcmp-style comparison of pReader's current term against pTerm. +** If isPrefix, equality means equal through nTerm bytes. +*/ +static int leafReaderTermCmp(LeafReader *pReader, + const char *pTerm, int nTerm, int isPrefix){ + int c, n = pReader->term.nDataterm.nData : nTerm; + if( n==0 ){ + if( pReader->term.nData>0 ) return -1; + if(nTerm>0 ) return 1; + return 0; + } + + c = memcmp(pReader->term.pData, pTerm, n); + if( c!=0 ) return c; + if( isPrefix && n==nTerm ) return 0; + return pReader->term.nData - nTerm; +} + + +/****************************************************************/ +/* LeavesReader wraps LeafReader to allow iterating over the entire +** leaf layer of the tree. +*/ +typedef struct LeavesReader { + int idx; /* Index within the segment. */ + + sqlite3_stmt *pStmt; /* Statement we're streaming leaves from. */ + int eof; /* we've seen SQLITE_DONE from pStmt. */ + + LeafReader leafReader; /* reader for the current leaf. */ + DataBuffer rootData; /* root data for inline. */ +} LeavesReader; + +/* Access the current term. */ +static int leavesReaderTermBytes(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderTermBytes(&pReader->leafReader); +} +static const char *leavesReaderTerm(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderTerm(&pReader->leafReader); +} + +/* Access the doclist data for the current term. */ +static int leavesReaderDataBytes(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderDataBytes(&pReader->leafReader); +} +static const char *leavesReaderData(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderData(&pReader->leafReader); +} + +static int leavesReaderAtEnd(LeavesReader *pReader){ + return pReader->eof; +} + +/* loadSegmentLeaves() may not read all the way to SQLITE_DONE, thus +** leaving the statement handle open, which locks the table. +*/ +/* TODO(shess) This "solution" is not satisfactory. Really, there +** should be check-in function for all statement handles which +** arranges to call sqlite3_reset(). This most likely will require +** modification to control flow all over the place, though, so for now +** just punt. +** +** Note the the current system assumes that segment merges will run to +** completion, which is why this particular probably hasn't arisen in +** this case. Probably a brittle assumption. +*/ +static int leavesReaderReset(LeavesReader *pReader){ + return sqlite3_reset(pReader->pStmt); +} + +static void leavesReaderDestroy(LeavesReader *pReader){ + leafReaderDestroy(&pReader->leafReader); + dataBufferDestroy(&pReader->rootData); + SCRAMBLE(pReader); +} + +/* Initialize pReader with the given root data (if iStartBlockid==0 +** the leaf data was entirely contained in the root), or from the +** stream of blocks between iStartBlockid and iEndBlockid, inclusive. +*/ +static int leavesReaderInit(fulltext_vtab *v, + int idx, + sqlite_int64 iStartBlockid, + sqlite_int64 iEndBlockid, + const char *pRootData, int nRootData, + LeavesReader *pReader){ + CLEAR(pReader); + pReader->idx = idx; + + dataBufferInit(&pReader->rootData, 0); + if( iStartBlockid==0 ){ + /* Entire leaf level fit in root data. */ + dataBufferReplace(&pReader->rootData, pRootData, nRootData); + leafReaderInit(pReader->rootData.pData, pReader->rootData.nData, + &pReader->leafReader); + }else{ + sqlite3_stmt *s; + int rc = sql_get_leaf_statement(v, idx, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iStartBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ){ + pReader->eof = 1; + return SQLITE_OK; + } + if( rc!=SQLITE_ROW ) return rc; + + pReader->pStmt = s; + leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), + sqlite3_column_bytes(pReader->pStmt, 0), + &pReader->leafReader); + } + return SQLITE_OK; +} + +/* Step the current leaf forward to the next term. If we reach the +** end of the current leaf, step forward to the next leaf block. +*/ +static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){ + assert( !leavesReaderAtEnd(pReader) ); + leafReaderStep(&pReader->leafReader); + + if( leafReaderAtEnd(&pReader->leafReader) ){ + int rc; + if( pReader->rootData.pData ){ + pReader->eof = 1; + return SQLITE_OK; + } + rc = sqlite3_step(pReader->pStmt); + if( rc!=SQLITE_ROW ){ + pReader->eof = 1; + return rc==SQLITE_DONE ? SQLITE_OK : rc; + } + leafReaderDestroy(&pReader->leafReader); + leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), + sqlite3_column_bytes(pReader->pStmt, 0), + &pReader->leafReader); + } + return SQLITE_OK; +} + +/* Order LeavesReaders by their term, ignoring idx. Readers at eof +** always sort to the end. +*/ +static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){ + if( leavesReaderAtEnd(lr1) ){ + if( leavesReaderAtEnd(lr2) ) return 0; + return 1; + } + if( leavesReaderAtEnd(lr2) ) return -1; + + return leafReaderTermCmp(&lr1->leafReader, + leavesReaderTerm(lr2), leavesReaderTermBytes(lr2), + 0); +} + +/* Similar to leavesReaderTermCmp(), with additional ordering by idx +** so that older segments sort before newer segments. +*/ +static int leavesReaderCmp(LeavesReader *lr1, LeavesReader *lr2){ + int c = leavesReaderTermCmp(lr1, lr2); + if( c!=0 ) return c; + return lr1->idx-lr2->idx; +} + +/* Assume that pLr[1]..pLr[nLr] are sorted. Bubble pLr[0] into its +** sorted position. +*/ +static void leavesReaderReorder(LeavesReader *pLr, int nLr){ + while( nLr>1 && leavesReaderCmp(pLr, pLr+1)>0 ){ + LeavesReader tmp = pLr[0]; + pLr[0] = pLr[1]; + pLr[1] = tmp; + nLr--; + pLr++; + } +} + +/* Initializes pReaders with the segments from level iLevel, returning +** the number of segments in *piReaders. Leaves pReaders in sorted +** order. +*/ +static int leavesReadersInit(fulltext_vtab *v, int iLevel, + LeavesReader *pReaders, int *piReaders){ + sqlite3_stmt *s; + int i, rc = sql_get_statement(v, SEGDIR_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + i = 0; + while( (rc = sqlite3_step(s))==SQLITE_ROW ){ + sqlite_int64 iStart = sqlite3_column_int64(s, 0); + sqlite_int64 iEnd = sqlite3_column_int64(s, 1); + const char *pRootData = sqlite3_column_blob(s, 2); + int nRootData = sqlite3_column_bytes(s, 2); + + assert( i0 ){ + leavesReaderDestroy(&pReaders[i]); + } + return rc; + } + + *piReaders = i; + + /* Leave our results sorted by term, then age. */ + while( i-- ){ + leavesReaderReorder(pReaders+i, *piReaders-i); + } + return SQLITE_OK; +} + +/* Merge doclists from pReaders[nReaders] into a single doclist, which +** is written to pWriter. Assumes pReaders is ordered oldest to +** newest. +*/ +/* TODO(shess) Consider putting this inline in segmentMerge(). */ +static int leavesReadersMerge(fulltext_vtab *v, + LeavesReader *pReaders, int nReaders, + LeafWriter *pWriter){ + DLReader dlReaders[MERGE_COUNT]; + const char *pTerm = leavesReaderTerm(pReaders); + int i, nTerm = leavesReaderTermBytes(pReaders); + + assert( nReaders<=MERGE_COUNT ); + + for(i=0; i0 ){ + rc = leavesReaderStep(v, lrs+i); + if( rc!=SQLITE_OK ) goto err; + + /* Reorder by term, then by age. */ + leavesReaderReorder(lrs+i, MERGE_COUNT-i); + } + } + + for(i=0; i0 ); + + /* Process while the prefix matches. */ + while( !leavesReaderAtEnd(pReader) ){ + /* TODO(shess) Really want leavesReaderTermCmp(), but that name is + ** already taken to compare the terms of two LeavesReaders. Think + ** on a better name. [Meanwhile, break encapsulation rather than + ** use a confusing name.] + */ + int rc; + int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix); + if( c==0 ){ + const char *pData = leavesReaderData(pReader); + int nData = leavesReaderDataBytes(pReader); + if( out->nData==0 ){ + dataBufferReplace(out, pData, nData); + }else{ + DataBuffer result; + dataBufferInit(&result, out->nData+nData); + docListUnion(out->pData, out->nData, pData, nData, &result); + dataBufferDestroy(out); + *out = result; + /* TODO(shess) Rather than destroy out, we could retain it for + ** later reuse. + */ + } + } + if( c>0 ) break; /* Past any possible matches. */ + + rc = leavesReaderStep(v, pReader); + if( rc!=SQLITE_OK ) return rc; + } + return SQLITE_OK; +} + +/* Call loadSegmentLeavesInt() with pData/nData as input. */ +static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + LeavesReader reader; + int rc; + + assert( nData>1 ); + assert( *pData=='\0' ); + rc = leavesReaderInit(v, 0, 0, 0, pData, nData, &reader); + if( rc!=SQLITE_OK ) return rc; + + rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out); + leavesReaderReset(&reader); + leavesReaderDestroy(&reader); + return rc; +} + +/* Call loadSegmentLeavesInt() with the leaf nodes from iStartLeaf to +** iEndLeaf (inclusive) as input, and merge the resulting doclist into +** out. +*/ +static int loadSegmentLeaves(fulltext_vtab *v, + sqlite_int64 iStartLeaf, sqlite_int64 iEndLeaf, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + int rc; + LeavesReader reader; + + assert( iStartLeaf<=iEndLeaf ); + rc = leavesReaderInit(v, 0, iStartLeaf, iEndLeaf, NULL, 0, &reader); + if( rc!=SQLITE_OK ) return rc; + + rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out); + leavesReaderReset(&reader); + leavesReaderDestroy(&reader); + return rc; +} + +/* Taking pData/nData as an interior node, find the sequence of child +** nodes which could include pTerm/nTerm/isPrefix. Note that the +** interior node terms logically come between the blocks, so there is +** one more blockid than there are terms (that block contains terms >= +** the last interior-node term). +*/ +/* TODO(shess) The calling code may already know that the end child is +** not worth calculating, because the end may be in a later sibling +** node. Consider whether breaking symmetry is worthwhile. I suspect +** it is not worthwhile. +*/ +static void getChildrenContaining(const char *pData, int nData, + const char *pTerm, int nTerm, int isPrefix, + sqlite_int64 *piStartChild, + sqlite_int64 *piEndChild){ + InteriorReader reader; + + assert( nData>1 ); + assert( *pData!='\0' ); + interiorReaderInit(pData, nData, &reader); + + /* Scan for the first child which could contain pTerm/nTerm. */ + while( !interiorReaderAtEnd(&reader) ){ + if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break; + interiorReaderStep(&reader); + } + *piStartChild = interiorReaderCurrentBlockid(&reader); + + /* Keep scanning to find a term greater than our term, using prefix + ** comparison if indicated. If isPrefix is false, this will be the + ** same blockid as the starting block. + */ + while( !interiorReaderAtEnd(&reader) ){ + if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break; + interiorReaderStep(&reader); + } + *piEndChild = interiorReaderCurrentBlockid(&reader); + + interiorReaderDestroy(&reader); + + /* Children must ascend, and if !prefix, both must be the same. */ + assert( *piEndChild>=*piStartChild ); + assert( isPrefix || *piStartChild==*piEndChild ); +} + +/* Read block at iBlockid and pass it with other params to +** getChildrenContaining(). +*/ +static int loadAndGetChildrenContaining( + fulltext_vtab *v, + sqlite_int64 iBlockid, + const char *pTerm, int nTerm, int isPrefix, + sqlite_int64 *piStartChild, sqlite_int64 *piEndChild +){ + sqlite3_stmt *s = NULL; + int rc; + + assert( iBlockid!=0 ); + assert( pTerm!=NULL ); + assert( nTerm!=0 ); /* TODO(shess) Why not allow this? */ + assert( piStartChild!=NULL ); + assert( piEndChild!=NULL ); + + rc = sql_get_statement(v, BLOCK_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ) return SQLITE_ERROR; + if( rc!=SQLITE_ROW ) return rc; + + getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0), + pTerm, nTerm, isPrefix, piStartChild, piEndChild); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain + * locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + + return SQLITE_OK; +} + +/* Traverse the tree represented by pData[nData] looking for +** pTerm[nTerm], placing its doclist into *out. This is internal to +** loadSegment() to make error-handling cleaner. +*/ +static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData, + sqlite_int64 iLeavesEnd, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + /* Special case where root is a leaf. */ + if( *pData=='\0' ){ + return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out); + }else{ + int rc; + sqlite_int64 iStartChild, iEndChild; + + /* Process pData as an interior node, then loop down the tree + ** until we find the set of leaf nodes to scan for the term. + */ + getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, + &iStartChild, &iEndChild); + while( iStartChild>iLeavesEnd ){ + sqlite_int64 iNextStart, iNextEnd; + rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix, + &iNextStart, &iNextEnd); + if( rc!=SQLITE_OK ) return rc; + + /* If we've branched, follow the end branch, too. */ + if( iStartChild!=iEndChild ){ + sqlite_int64 iDummy; + rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix, + &iDummy, &iNextEnd); + if( rc!=SQLITE_OK ) return rc; + } + + assert( iNextStart<=iNextEnd ); + iStartChild = iNextStart; + iEndChild = iNextEnd; + } + assert( iStartChild<=iLeavesEnd ); + assert( iEndChild<=iLeavesEnd ); + + /* Scan through the leaf segments for doclists. */ + return loadSegmentLeaves(v, iStartChild, iEndChild, + pTerm, nTerm, isPrefix, out); + } +} + +/* Call loadSegmentInt() to collect the doclist for pTerm/nTerm, then +** merge its doclist over *out (any duplicate doclists read from the +** segment rooted at pData will overwrite those in *out). +*/ +/* TODO(shess) Consider changing this to determine the depth of the +** leaves using either the first characters of interior nodes (when +** ==1, we're one level above the leaves), or the first character of +** the root (which will describe the height of the tree directly). +** Either feels somewhat tricky to me. +*/ +/* TODO(shess) The current merge is likely to be slow for large +** doclists (though it should process from newest/smallest to +** oldest/largest, so it may not be that bad). It might be useful to +** modify things to allow for N-way merging. This could either be +** within a segment, with pairwise merges across segments, or across +** all segments at once. +*/ +static int loadSegment(fulltext_vtab *v, const char *pData, int nData, + sqlite_int64 iLeavesEnd, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + DataBuffer result; + int rc; + + assert( nData>1 ); + + /* This code should never be called with buffered updates. */ + assert( v->nPendingData<0 ); + + dataBufferInit(&result, 0); + rc = loadSegmentInt(v, pData, nData, iLeavesEnd, + pTerm, nTerm, isPrefix, &result); + if( rc==SQLITE_OK && result.nData>0 ){ + if( out->nData==0 ){ + DataBuffer tmp = *out; + *out = result; + result = tmp; + }else{ + DataBuffer merged; + DLReader readers[2]; + + dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); + dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); + dataBufferInit(&merged, out->nData+result.nData); + docListMerge(&merged, readers, 2); + dataBufferDestroy(out); + *out = merged; + dlrDestroy(&readers[0]); + dlrDestroy(&readers[1]); + } + } + dataBufferDestroy(&result); + return rc; +} + +/* Scan the database and merge together the posting lists for the term +** into *out. +*/ +static int termSelect(fulltext_vtab *v, int iColumn, + const char *pTerm, int nTerm, int isPrefix, + DocListType iType, DataBuffer *out){ + DataBuffer doclist; + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + /* This code should never be called with buffered updates. */ + assert( v->nPendingData<0 ); + + dataBufferInit(&doclist, 0); + + /* Traverse the segments from oldest to newest so that newer doclist + ** elements for given docids overwrite older elements. + */ + while( (rc = sqlite3_step(s))==SQLITE_ROW ){ + const char *pData = sqlite3_column_blob(s, 0); + const int nData = sqlite3_column_bytes(s, 0); + const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1); + rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix, + &doclist); + if( rc!=SQLITE_OK ) goto err; + } + if( rc==SQLITE_DONE ){ + if( doclist.nData!=0 ){ + /* TODO(shess) The old term_select_all() code applied the column + ** restrict as we merged segments, leading to smaller buffers. + ** This is probably worthwhile to bring back, once the new storage + ** system is checked in. + */ + if( iColumn==v->nColumn) iColumn = -1; + docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, + iColumn, iType, out); + } + rc = SQLITE_OK; + } + + err: + dataBufferDestroy(&doclist); + return rc; +} + +/****************************************************************/ +/* Used to hold hashtable data for sorting. */ +typedef struct TermData { + const char *pTerm; + int nTerm; + DLCollector *pCollector; +} TermData; + +/* Orders TermData elements in strcmp fashion ( <0 for less-than, 0 +** for equal, >0 for greater-than). +*/ +static int termDataCmp(const void *av, const void *bv){ + const TermData *a = (const TermData *)av; + const TermData *b = (const TermData *)bv; + int n = a->nTermnTerm ? a->nTerm : b->nTerm; + int c = memcmp(a->pTerm, b->pTerm, n); + if( c!=0 ) return c; + return a->nTerm-b->nTerm; +} + +/* Order pTerms data by term, then write a new level 0 segment using +** LeafWriter. +*/ +static int writeZeroSegment(fulltext_vtab *v, fts2Hash *pTerms){ + fts2HashElem *e; + int idx, rc, i, n; + TermData *pData; + LeafWriter writer; + DataBuffer dl; + + /* Determine the next index at level 0, merging as necessary. */ + rc = segdirNextIndex(v, 0, &idx); + if( rc!=SQLITE_OK ) return rc; + + n = fts2HashCount(pTerms); + pData = malloc(n*sizeof(TermData)); + + for(i = 0, e = fts2HashFirst(pTerms); e; i++, e = fts2HashNext(e)){ + assert( i1 ) qsort(pData, n, sizeof(*pData), termDataCmp); + + /* TODO(shess) Refactor so that we can write directly to the segment + ** DataBuffer, as happens for segment merges. + */ + leafWriterInit(0, idx, &writer); + dataBufferInit(&dl, 0); + for(i=0; inPendingData>=0 ){ + fts2HashElem *e; + for(e=fts2HashFirst(&v->pendingTerms); e; e=fts2HashNext(e)){ + dlcDelete(fts2HashData(e)); + } + fts2HashClear(&v->pendingTerms); + v->nPendingData = -1; + } + return SQLITE_OK; +} + +/* If pendingTerms has data, flush it to a level-zero segment, and +** free it. +*/ +static int flushPendingTerms(fulltext_vtab *v){ + if( v->nPendingData>=0 ){ + int rc = writeZeroSegment(v, &v->pendingTerms); + if( rc==SQLITE_OK ) clearPendingTerms(v); + return rc; + } + return SQLITE_OK; +} + +/* If pendingTerms is "too big", or docid is out of order, flush it. +** Regardless, be certain that pendingTerms is initialized for use. +*/ +static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid){ + /* TODO(shess) Explore whether partially flushing the buffer on + ** forced-flush would provide better performance. I suspect that if + ** we ordered the doclists by size and flushed the largest until the + ** buffer was half empty, that would let the less frequent terms + ** generate longer doclists. + */ + if( iDocid<=v->iPrevDocid || v->nPendingData>kPendingThreshold ){ + int rc = flushPendingTerms(v); + if( rc!=SQLITE_OK ) return rc; + } + if( v->nPendingData<0 ){ + fts2HashInit(&v->pendingTerms, FTS2_HASH_STRING, 1); + v->nPendingData = 0; + } + v->iPrevDocid = iDocid; + return SQLITE_OK; +} + +/* This function implements the xUpdate callback; it is the top-level entry + * point for inserting, deleting or updating a row in a full-text table. */ +static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, + sqlite_int64 *pRowid){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + int rc; + + TRACE(("FTS2 Update %p\n", pVtab)); + + if( nArg<2 ){ + rc = index_delete(v, sqlite3_value_int64(ppArg[0])); + } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){ + /* An update: + * ppArg[0] = old rowid + * ppArg[1] = new rowid + * ppArg[2..2+v->nColumn-1] = values + * ppArg[2+v->nColumn] = value for magic column (we ignore this) + */ + sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]); + if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER || + sqlite3_value_int64(ppArg[1]) != rowid ){ + rc = SQLITE_ERROR; /* we don't allow changing the rowid */ + } else { + assert( nArg==2+v->nColumn+1); + rc = index_update(v, rowid, &ppArg[2]); + } + } else { + /* An insert: + * ppArg[1] = requested rowid + * ppArg[2..2+v->nColumn-1] = values + * ppArg[2+v->nColumn] = value for magic column (we ignore this) + */ + assert( nArg==2+v->nColumn+1); + rc = index_insert(v, ppArg[1], &ppArg[2], pRowid); + } + + return rc; +} + +static int fulltextSync(sqlite3_vtab *pVtab){ + TRACE(("FTS2 xSync()\n")); + return flushPendingTerms((fulltext_vtab *)pVtab); +} + +static int fulltextBegin(sqlite3_vtab *pVtab){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + TRACE(("FTS2 xBegin()\n")); + + /* Any buffered updates should have been cleared by the previous + ** transaction. + */ + assert( v->nPendingData<0 ); + return clearPendingTerms(v); +} + +static int fulltextCommit(sqlite3_vtab *pVtab){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + TRACE(("FTS2 xCommit()\n")); + + /* Buffered updates should have been cleared by fulltextSync(). */ + assert( v->nPendingData<0 ); + return clearPendingTerms(v); +} + +static int fulltextRollback(sqlite3_vtab *pVtab){ + TRACE(("FTS2 xRollback()\n")); + return clearPendingTerms((fulltext_vtab *)pVtab); +} + +/* +** Implementation of the snippet() function for FTS2 +*/ +static void snippetFunc( + sqlite3_context *pContext, + int argc, + sqlite3_value **argv +){ + fulltext_cursor *pCursor; + if( argc<1 ) return; + if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || + sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ + sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1); + }else{ + const char *zStart = ""; + const char *zEnd = ""; + const char *zEllipsis = "..."; + memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); + if( argc>=2 ){ + zStart = (const char*)sqlite3_value_text(argv[1]); + if( argc>=3 ){ + zEnd = (const char*)sqlite3_value_text(argv[2]); + if( argc>=4 ){ + zEllipsis = (const char*)sqlite3_value_text(argv[3]); + } + } + } + snippetAllOffsets(pCursor); + snippetText(pCursor, zStart, zEnd, zEllipsis); + sqlite3_result_text(pContext, pCursor->snippet.zSnippet, + pCursor->snippet.nSnippet, SQLITE_STATIC); + } +} + +/* +** Implementation of the offsets() function for FTS2 +*/ +static void snippetOffsetsFunc( + sqlite3_context *pContext, + int argc, + sqlite3_value **argv +){ + fulltext_cursor *pCursor; + if( argc<1 ) return; + if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || + sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ + sqlite3_result_error(pContext, "illegal first argument to offsets",-1); + }else{ + memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); + snippetAllOffsets(pCursor); + snippetOffsetText(&pCursor->snippet); + sqlite3_result_text(pContext, + pCursor->snippet.zOffset, pCursor->snippet.nOffset, + SQLITE_STATIC); + } +} + +/* +** This routine implements the xFindFunction method for the FTS2 +** virtual table. +*/ +static int fulltextFindFunction( + sqlite3_vtab *pVtab, + int nArg, + const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg +){ + if( strcmp(zName,"snippet")==0 ){ + *pxFunc = snippetFunc; + return 1; + }else if( strcmp(zName,"offsets")==0 ){ + *pxFunc = snippetOffsetsFunc; + return 1; + } + return 0; +} + +/* +** Rename an fts2 table. +*/ +static int fulltextRename( + sqlite3_vtab *pVtab, + const char *zName +){ + fulltext_vtab *p = (fulltext_vtab *)pVtab; + int rc = SQLITE_NOMEM; + char *zSql = sqlite3_mprintf( + "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';" + "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';" + "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';" + , p->zDb, p->zName, zName + , p->zDb, p->zName, zName + , p->zDb, p->zName, zName + ); + if( zSql ){ + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } + return rc; +} + +static const sqlite3_module fts2Module = { + /* iVersion */ 0, + /* xCreate */ fulltextCreate, + /* xConnect */ fulltextConnect, + /* xBestIndex */ fulltextBestIndex, + /* xDisconnect */ fulltextDisconnect, + /* xDestroy */ fulltextDestroy, + /* xOpen */ fulltextOpen, + /* xClose */ fulltextClose, + /* xFilter */ fulltextFilter, + /* xNext */ fulltextNext, + /* xEof */ fulltextEof, + /* xColumn */ fulltextColumn, + /* xRowid */ fulltextRowid, + /* xUpdate */ fulltextUpdate, + /* xBegin */ fulltextBegin, + /* xSync */ fulltextSync, + /* xCommit */ fulltextCommit, + /* xRollback */ fulltextRollback, + /* xFindFunction */ fulltextFindFunction, + /* xRename */ fulltextRename, +}; + +static void hashDestroy(void *p){ + fts2Hash *pHash = (fts2Hash *)p; + sqlite3Fts2HashClear(pHash); + sqlite3_free(pHash); +} + +/* +** The fts2 built-in tokenizers - "simple" and "porter" - are implemented +** in files fts2_tokenizer1.c and fts2_porter.c respectively. The following +** two forward declarations are for functions declared in these files +** used to retrieve the respective implementations. +** +** Calling sqlite3Fts2SimpleTokenizerModule() sets the value pointed +** to by the argument to point a the "simple" tokenizer implementation. +** Function ...PorterTokenizerModule() sets *pModule to point to the +** porter tokenizer/stemmer implementation. +*/ +void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); +void sqlite3Fts2PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); +void sqlite3Fts2IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); + +int sqlite3Fts2InitHashTable(sqlite3 *, fts2Hash *, const char *); + +/* +** Initialise the fts2 extension. If this extension is built as part +** of the sqlite library, then this function is called directly by +** SQLite. If fts2 is built as a dynamically loadable extension, this +** function is called by the sqlite3_extension_init() entry point. +*/ +int sqlite3Fts2Init(sqlite3 *db){ + int rc = SQLITE_OK; + fts2Hash *pHash = 0; + const sqlite3_tokenizer_module *pSimple = 0; + const sqlite3_tokenizer_module *pPorter = 0; + const sqlite3_tokenizer_module *pIcu = 0; + + sqlite3Fts2SimpleTokenizerModule(&pSimple); + sqlite3Fts2PorterTokenizerModule(&pPorter); +#ifdef SQLITE_ENABLE_ICU + sqlite3Fts2IcuTokenizerModule(&pIcu); +#endif + + /* Allocate and initialise the hash-table used to store tokenizers. */ + pHash = sqlite3_malloc(sizeof(fts2Hash)); + if( !pHash ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1); + } + + /* Load the built-in tokenizers into the hash table */ + if( rc==SQLITE_OK ){ + if( sqlite3Fts2HashInsert(pHash, "simple", 7, (void *)pSimple) + || sqlite3Fts2HashInsert(pHash, "porter", 7, (void *)pPorter) + || (pIcu && sqlite3Fts2HashInsert(pHash, "icu", 4, (void *)pIcu)) + ){ + rc = SQLITE_NOMEM; + } + } + + /* Create the virtual table wrapper around the hash-table and overload + ** the two scalar functions. If this is successful, register the + ** module with sqlite. + */ + if( SQLITE_OK==rc + && SQLITE_OK==(rc = sqlite3Fts2InitHashTable(db, pHash, "fts2_tokenizer")) + && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) + && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1)) + ){ + return sqlite3_create_module_v2( + db, "fts2", &fts2Module, (void *)pHash, hashDestroy + ); + } + + /* An error has occured. Delete the hash table and return the error code. */ + assert( rc!=SQLITE_OK ); + if( pHash ){ + sqlite3Fts2HashClear(pHash); + sqlite3_free(pHash); + } + return rc; +} + +#if !SQLITE_CORE +int sqlite3_extension_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi) + return sqlite3Fts2Init(db); +} +#endif + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.h new file mode 100644 index 0000000..4da4c38 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2.h @@ -0,0 +1,26 @@ +/* +** 2006 Oct 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. +** +****************************************************************************** +** +** This header file is used by programs that want to link against the +** FTS2 library. All it does is declare the sqlite3Fts2Init() interface. +*/ +#include "sqlite3.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int sqlite3Fts2Init(sqlite3 *db); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.c new file mode 100644 index 0000000..fcd5cc2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.c @@ -0,0 +1,369 @@ +/* +** 2001 September 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 is the implementation of generic hash-tables used in SQLite. +** We've modified it slightly to serve as a standalone hash table +** implementation for the full-text indexing module. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS2 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS2 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) + +#include +#include +#include + +#include "fts2_hash.h" + +static void *malloc_and_zero(int n){ + void *p = malloc(n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +** keyClass is one of the constants +** FTS2_HASH_BINARY or FTS2_HASH_STRING. The value of keyClass +** determines what kind of key the hash table will use. "copyKey" is +** true if the hash table should make its own private copy of keys and +** false if it should just use the supplied pointer. +*/ +void sqlite3Fts2HashInit(fts2Hash *pNew, int keyClass, int copyKey){ + assert( pNew!=0 ); + assert( keyClass>=FTS2_HASH_STRING && keyClass<=FTS2_HASH_BINARY ); + pNew->keyClass = keyClass; + pNew->copyKey = copyKey; + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; + pNew->xMalloc = malloc_and_zero; + pNew->xFree = free; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +void sqlite3Fts2HashClear(fts2Hash *pH){ + fts2HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + if( pH->ht ) pH->xFree(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + fts2HashElem *next_elem = elem->next; + if( pH->copyKey && elem->pKey ){ + pH->xFree(elem->pKey); + } + pH->xFree(elem); + elem = next_elem; + } + pH->count = 0; +} + +/* +** Hash and comparison functions when the mode is FTS2_HASH_STRING +*/ +static int strHash(const void *pKey, int nKey){ + const char *z = (const char *)pKey; + int h = 0; + if( nKey<=0 ) nKey = (int) strlen(z); + while( nKey > 0 ){ + h = (h<<3) ^ h ^ *z++; + nKey--; + } + return h & 0x7fffffff; +} +static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return strncmp((const char*)pKey1,(const char*)pKey2,n1); +} + +/* +** Hash and comparison functions when the mode is FTS2_HASH_BINARY +*/ +static int binHash(const void *pKey, int nKey){ + int h = 0; + const char *z = (const char *)pKey; + while( nKey-- > 0 ){ + h = (h<<3) ^ h ^ *(z++); + } + return h & 0x7fffffff; +} +static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return memcmp(pKey1,pKey2,n1); +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** The C syntax in this function definition may be unfamilar to some +** programmers, so we provide the following additional explanation: +** +** The name of the function is "hashFunction". The function takes a +** single parameter "keyClass". The return value of hashFunction() +** is a pointer to another function. Specifically, the return value +** of hashFunction() is a pointer to a function that takes two parameters +** with types "const void*" and "int" and returns an "int". +*/ +static int (*hashFunction(int keyClass))(const void*,int){ + if( keyClass==FTS2_HASH_STRING ){ + return &strHash; + }else{ + assert( keyClass==FTS2_HASH_BINARY ); + return &binHash; + } +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** For help in interpreted the obscure C code in the function definition, +** see the header comment on the previous function. +*/ +static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ + if( keyClass==FTS2_HASH_STRING ){ + return &strCompare; + }else{ + assert( keyClass==FTS2_HASH_BINARY ); + return &binCompare; + } +} + +/* Link an element into the hash table +*/ +static void insertElement( + fts2Hash *pH, /* The complete hash table */ + struct _fts2ht *pEntry, /* The entry into which pNew is inserted */ + fts2HashElem *pNew /* The element to be inserted */ +){ + fts2HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** "new_size" must be a power of 2. The hash table might fail +** to resize if sqliteMalloc() fails. +*/ +static void rehash(fts2Hash *pH, int new_size){ + struct _fts2ht *new_ht; /* The new hash table */ + fts2HashElem *elem, *next_elem; /* For looping over existing elements */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( (new_size & (new_size-1))==0 ); + new_ht = (struct _fts2ht *)pH->xMalloc( new_size*sizeof(struct _fts2ht) ); + if( new_ht==0 ) return; + if( pH->ht ) pH->xFree(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size; + xHash = hashFunction(pH->keyClass); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + next_elem = elem->next; + insertElement(pH, &new_ht[h], elem); + } +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. +*/ +static fts2HashElem *findElementGivenHash( + const fts2Hash *pH, /* The pH to be searched */ + const void *pKey, /* The key we are searching for */ + int nKey, + int h /* The hash for this key. */ +){ + fts2HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + int (*xCompare)(const void*,int,const void*,int); /* comparison function */ + + if( pH->ht ){ + struct _fts2ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + xCompare = compareFunction(pH->keyClass); + while( count-- && elem ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void removeElementGivenHash( + fts2Hash *pH, /* The pH containing "elem" */ + fts2HashElem* elem, /* The element to be removed from the pH */ + int h /* Hash value for the element */ +){ + struct _fts2ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; + } + if( pH->copyKey && elem->pKey ){ + pH->xFree(elem->pKey); + } + pH->xFree( elem ); + pH->count--; + if( pH->count<=0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + fts2HashClear(pH); + } +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +void *sqlite3Fts2HashFind(const fts2Hash *pH, const void *pKey, int nKey){ + int h; /* A hash on key */ + fts2HashElem *elem; /* The element that matches key */ + int (*xHash)(const void*,int); /* The hash function */ + + if( pH==0 || pH->ht==0 ) return 0; + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + h = (*xHash)(pKey,nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1)); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey,nKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created. A copy of the key is made if the copyKey +** flag is set. NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +void *sqlite3Fts2HashInsert( + fts2Hash *pH, /* The hash table to insert into */ + const void *pKey, /* The key */ + int nKey, /* Number of bytes in the key */ + void *data /* The data */ +){ + int hraw; /* Raw hash value of the key */ + int h; /* the hash of the key modulo hash table size */ + fts2HashElem *elem; /* Used to loop thru the element list */ + fts2HashElem *new_elem; /* New element added to the pH */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( pH!=0 ); + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + hraw = (*xHash)(pKey, nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + elem = findElementGivenHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + } + return old_data; + } + if( data==0 ) return 0; + new_elem = (fts2HashElem*)pH->xMalloc( sizeof(fts2HashElem) ); + if( new_elem==0 ) return data; + if( pH->copyKey && pKey!=0 ){ + new_elem->pKey = pH->xMalloc( nKey ); + if( new_elem->pKey==0 ){ + pH->xFree(new_elem); + return data; + } + memcpy((void*)new_elem->pKey, pKey, nKey); + }else{ + new_elem->pKey = (void*)pKey; + } + new_elem->nKey = nKey; + pH->count++; + if( pH->htsize==0 ){ + rehash(pH,8); + if( pH->htsize==0 ){ + pH->count = 0; + pH->xFree(new_elem); + return data; + } + } + if( pH->count > pH->htsize ){ + rehash(pH,pH->htsize*2); + } + assert( pH->htsize>0 ); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + insertElement(pH, &pH->ht[h], new_elem); + new_elem->data = data; + return 0; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.h new file mode 100644 index 0000000..97f3529 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_hash.h @@ -0,0 +1,112 @@ +/* +** 2001 September 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 is the header file for the generic hash-table implemenation +** used in SQLite. We've modified it slightly to serve as a standalone +** hash table implementation for the full-text indexing module. +** +*/ +#ifndef _FTS2_HASH_H_ +#define _FTS2_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct fts2Hash fts2Hash; +typedef struct fts2HashElem fts2HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct fts2Hash { + char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ + char copyKey; /* True if copy of key made on insert */ + int count; /* Number of entries in this table */ + fts2HashElem *first; /* The first element of the array */ + void *(*xMalloc)(int); /* malloc() function to use */ + void (*xFree)(void *); /* free() function to use */ + int htsize; /* Number of buckets in the hash table */ + struct _fts2ht { /* the hash table */ + int count; /* Number of entries with this hash */ + fts2HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct fts2HashElem { + fts2HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** There are 2 different modes of operation for a hash table: +** +** FTS2_HASH_STRING pKey points to a string that is nKey bytes long +** (including the null-terminator, if any). Case +** is respected in comparisons. +** +** FTS2_HASH_BINARY pKey points to binary data nKey bytes long. +** memcmp() is used to compare keys. +** +** A copy of the key is made if the copyKey parameter to fts2HashInit is 1. +*/ +#define FTS2_HASH_STRING 1 +#define FTS2_HASH_BINARY 2 + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +void sqlite3Fts2HashInit(fts2Hash*, int keytype, int copyKey); +void *sqlite3Fts2HashInsert(fts2Hash*, const void *pKey, int nKey, void *pData); +void *sqlite3Fts2HashFind(const fts2Hash*, const void *pKey, int nKey); +void sqlite3Fts2HashClear(fts2Hash*); + +/* +** Shorthand for the functions above +*/ +#define fts2HashInit sqlite3Fts2HashInit +#define fts2HashInsert sqlite3Fts2HashInsert +#define fts2HashFind sqlite3Fts2HashFind +#define fts2HashClear sqlite3Fts2HashClear + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** fts2Hash h; +** fts2HashElem *p; +** ... +** for(p=fts2HashFirst(&h); p; p=fts2HashNext(p)){ +** SomeStructure *pData = fts2HashData(p); +** // do something with pData +** } +*/ +#define fts2HashFirst(H) ((H)->first) +#define fts2HashNext(E) ((E)->next) +#define fts2HashData(E) ((E)->data) +#define fts2HashKey(E) ((E)->pKey) +#define fts2HashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define fts2HashCount(H) ((H)->count) + +#endif /* _FTS2_HASH_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_icu.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_icu.c new file mode 100644 index 0000000..ed15f33 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_icu.c @@ -0,0 +1,257 @@ +/* +** 2007 June 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 implements a tokenizer for fts2 based on the ICU library. +** +** $Id: fts2_icu.c,v 1.1 2007/06/22 15:21:16 danielk1977 Exp $ +*/ + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) +#ifdef SQLITE_ENABLE_ICU + +#include +#include +#include "fts2_tokenizer.h" + +#include +#include +#include +#include + +typedef struct IcuTokenizer IcuTokenizer; +typedef struct IcuCursor IcuCursor; + +struct IcuTokenizer { + sqlite3_tokenizer base; + char *zLocale; +}; + +struct IcuCursor { + sqlite3_tokenizer_cursor base; + + UBreakIterator *pIter; /* ICU break-iterator object */ + int nChar; /* Number of UChar elements in pInput */ + UChar *aChar; /* Copy of input using utf-16 encoding */ + int *aOffset; /* Offsets of each character in utf-8 input */ + + int nBuffer; + char *zBuffer; + + int iToken; +}; + +/* +** Create a new tokenizer instance. +*/ +static int icuCreate( + int argc, /* Number of entries in argv[] */ + const char * const *argv, /* Tokenizer creation arguments */ + sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ +){ + IcuTokenizer *p; + int n = 0; + + if( argc>0 ){ + n = strlen(argv[0])+1; + } + p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n); + if( !p ){ + return SQLITE_NOMEM; + } + memset(p, 0, sizeof(IcuTokenizer)); + + if( n ){ + p->zLocale = (char *)&p[1]; + memcpy(p->zLocale, argv[0], n); + } + + *ppTokenizer = (sqlite3_tokenizer *)p; + + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int icuDestroy(sqlite3_tokenizer *pTokenizer){ + IcuTokenizer *p = (IcuTokenizer *)pTokenizer; + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is pInput[0..nBytes-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int icuOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *zInput, /* Input string */ + int nInput, /* Length of zInput in bytes */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + IcuTokenizer *p = (IcuTokenizer *)pTokenizer; + IcuCursor *pCsr; + + const int32_t opt = U_FOLD_CASE_DEFAULT; + UErrorCode status = U_ZERO_ERROR; + int nChar; + + UChar32 c; + int iInput = 0; + int iOut = 0; + + *ppCursor = 0; + + nChar = nInput+1; + pCsr = (IcuCursor *)sqlite3_malloc( + sizeof(IcuCursor) + /* IcuCursor */ + nChar * sizeof(UChar) + /* IcuCursor.aChar[] */ + (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ + ); + if( !pCsr ){ + return SQLITE_NOMEM; + } + memset(pCsr, 0, sizeof(IcuCursor)); + pCsr->aChar = (UChar *)&pCsr[1]; + pCsr->aOffset = (int *)&pCsr->aChar[nChar]; + + pCsr->aOffset[iOut] = iInput; + U8_NEXT(zInput, iInput, nInput, c); + while( c>0 ){ + int isError = 0; + c = u_foldCase(c, opt); + U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); + if( isError ){ + sqlite3_free(pCsr); + return SQLITE_ERROR; + } + pCsr->aOffset[iOut] = iInput; + + if( iInputpIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status); + if( !U_SUCCESS(status) ){ + sqlite3_free(pCsr); + return SQLITE_ERROR; + } + pCsr->nChar = iOut; + + ubrk_first(pCsr->pIter); + *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to icuOpen(). +*/ +static int icuClose(sqlite3_tokenizer_cursor *pCursor){ + IcuCursor *pCsr = (IcuCursor *)pCursor; + ubrk_close(pCsr->pIter); + sqlite3_free(pCsr->zBuffer); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* +** Extract the next token from a tokenization cursor. +*/ +static int icuNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ + const char **ppToken, /* OUT: *ppToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + IcuCursor *pCsr = (IcuCursor *)pCursor; + + int iStart = 0; + int iEnd = 0; + int nByte = 0; + + while( iStart==iEnd ){ + UChar32 c; + + iStart = ubrk_current(pCsr->pIter); + iEnd = ubrk_next(pCsr->pIter); + if( iEnd==UBRK_DONE ){ + return SQLITE_DONE; + } + + while( iStartaChar, iWhite, pCsr->nChar, c); + if( u_isspace(c) ){ + iStart = iWhite; + }else{ + break; + } + } + assert(iStart<=iEnd); + } + + do { + UErrorCode status = U_ZERO_ERROR; + if( nByte ){ + char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte); + if( !zNew ){ + return SQLITE_NOMEM; + } + pCsr->zBuffer = zNew; + pCsr->nBuffer = nByte; + } + + u_strToUTF8( + pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */ + &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */ + &status /* Output success/failure */ + ); + } while( nByte>pCsr->nBuffer ); + + *ppToken = pCsr->zBuffer; + *pnBytes = nByte; + *piStartOffset = pCsr->aOffset[iStart]; + *piEndOffset = pCsr->aOffset[iEnd]; + *piPosition = pCsr->iToken++; + + return SQLITE_OK; +} + +/* +** 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 */ +}; + +/* +** Set *ppModule to point at the implementation of the ICU tokenizer. +*/ +void sqlite3Fts2IcuTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &icuTokenizerModule; +} + +#endif /* defined(SQLITE_ENABLE_ICU) */ +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_porter.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_porter.c new file mode 100644 index 0000000..dab1849 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_porter.c @@ -0,0 +1,642 @@ +/* +** 2006 September 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. +** +************************************************************************* +** Implementation of the full-text-search tokenizer that implements +** a Porter stemmer. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS2 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS2 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) + + +#include +#include +#include +#include +#include + +#include "fts2_tokenizer.h" + +/* +** Class derived from sqlite3_tokenizer +*/ +typedef struct porter_tokenizer { + sqlite3_tokenizer base; /* Base class */ +} porter_tokenizer; + +/* +** Class derived from sqlit3_tokenizer_cursor +*/ +typedef struct porter_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *zInput; /* input we are tokenizing */ + int nInput; /* size of the input */ + int iOffset; /* current position in zInput */ + int iToken; /* index of next token to be returned */ + char *zToken; /* storage for current token */ + int nAllocated; /* space allocated to zToken buffer */ +} porter_tokenizer_cursor; + + +/* Forward declaration */ +static const sqlite3_tokenizer_module porterTokenizerModule; + + +/* +** Create a new tokenizer instance. +*/ +static int porterCreate( + int argc, const char * const *argv, + sqlite3_tokenizer **ppTokenizer +){ + porter_tokenizer *t; + t = (porter_tokenizer *) calloc(sizeof(*t), 1); + if( t==NULL ) return SQLITE_NOMEM; + + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int porterDestroy(sqlite3_tokenizer *pTokenizer){ + free(pTokenizer); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is zInput[0..nInput-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int porterOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *zInput, int nInput, /* String to be tokenized */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + porter_tokenizer_cursor *c; + + c = (porter_tokenizer_cursor *) malloc(sizeof(*c)); + if( c==NULL ) return SQLITE_NOMEM; + + c->zInput = zInput; + if( zInput==0 ){ + c->nInput = 0; + }else if( nInput<0 ){ + c->nInput = (int)strlen(zInput); + }else{ + c->nInput = nInput; + } + c->iOffset = 0; /* start tokenizing at the beginning */ + c->iToken = 0; + c->zToken = NULL; /* no space allocated, yet. */ + c->nAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** porterOpen() above. +*/ +static int porterClose(sqlite3_tokenizer_cursor *pCursor){ + porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; + free(c->zToken); + free(c); + return SQLITE_OK; +} +/* +** Vowel or consonant +*/ +static const char cType[] = { + 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 2, 1 +}; + +/* +** isConsonant() and isVowel() determine if their first character in +** the string they point to is a consonant or a vowel, according +** to Porter ruls. +** +** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. +** 'Y' is a consonant unless it follows another consonant, +** in which case it is a vowel. +** +** In these routine, the letters are in reverse order. So the 'y' rule +** is that 'y' is a consonant unless it is followed by another +** consonent. +*/ +static int isVowel(const char*); +static int isConsonant(const char *z){ + int j; + char x = *z; + if( x==0 ) return 0; + assert( x>='a' && x<='z' ); + j = cType[x-'a']; + if( j<2 ) return j; + return z[1]==0 || isVowel(z + 1); +} +static int isVowel(const char *z){ + int j; + char x = *z; + if( x==0 ) return 0; + assert( x>='a' && x<='z' ); + j = cType[x-'a']; + if( j<2 ) return 1-j; + return isConsonant(z + 1); +} + +/* +** Let any sequence of one or more vowels be represented by V and let +** C be sequence of one or more consonants. Then every word can be +** represented as: +** +** [C] (VC){m} [V] +** +** In prose: A word is an optional consonant followed by zero or +** vowel-consonant pairs followed by an optional vowel. "m" is the +** number of vowel consonant pairs. This routine computes the value +** of m for the first i bytes of a word. +** +** Return true if the m-value for z is 1 or more. In other words, +** return true if z contains at least one vowel that is followed +** by a consonant. +** +** In this routine z[] is in reverse order. So we are really looking +** for an instance of of a consonant followed by a vowel. +*/ +static int m_gt_0(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* Like mgt0 above except we are looking for a value of m which is +** exactly 1 +*/ +static int m_eq_1(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + if( *z==0 ) return 0; + while( isVowel(z) ){ z++; } + if( *z==0 ) return 1; + while( isConsonant(z) ){ z++; } + return *z==0; +} + +/* Like mgt0 above except we are looking for a value of m>1 instead +** or m>0 +*/ +static int m_gt_1(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + if( *z==0 ) return 0; + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* +** Return TRUE if there is a vowel anywhere within z[0..n-1] +*/ +static int hasVowel(const char *z){ + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* +** Return TRUE if the word ends in a double consonant. +** +** The text is reversed here. So we are really looking at +** the first two characters of z[]. +*/ +static int doubleConsonant(const char *z){ + return isConsonant(z) && z[0]==z[1] && isConsonant(z+1); +} + +/* +** Return TRUE if the word ends with three letters which +** are consonant-vowel-consonent and where the final consonant +** is not 'w', 'x', or 'y'. +** +** The word is reversed here. So we are really checking the +** first three letters and the first one cannot be in [wxy]. +*/ +static int star_oh(const char *z){ + return + z[0]!=0 && isConsonant(z) && + z[0]!='w' && z[0]!='x' && z[0]!='y' && + z[1]!=0 && isVowel(z+1) && + z[2]!=0 && isConsonant(z+2); +} + +/* +** If the word ends with zFrom and xCond() is true for the stem +** of the word that preceeds the zFrom ending, then change the +** ending to zTo. +** +** The input word *pz and zFrom are both in reverse order. zTo +** is in normal order. +** +** Return TRUE if zFrom matches. Return FALSE if zFrom does not +** match. Not that TRUE is returned even if xCond() fails and +** no substitution occurs. +*/ +static int stem( + char **pz, /* The word being stemmed (Reversed) */ + const char *zFrom, /* If the ending matches this... (Reversed) */ + const char *zTo, /* ... change the ending to this (not reversed) */ + int (*xCond)(const char*) /* Condition that must be true */ +){ + char *z = *pz; + while( *zFrom && *zFrom==*z ){ z++; zFrom++; } + if( *zFrom!=0 ) return 0; + if( xCond && !xCond(z) ) return 1; + while( *zTo ){ + *(--z) = *(zTo++); + } + *pz = z; + return 1; +} + +/* +** This is the fallback stemmer used when the porter stemmer is +** inappropriate. The input word is copied into the output with +** US-ASCII case folding. If the input word is too long (more +** than 20 bytes if it contains no digits or more than 6 bytes if +** it contains digits) then word is truncated to 20 or 6 bytes +** by taking 10 or 3 bytes from the beginning and end. +*/ +static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ + int i, mx, j; + int hasDigit = 0; + for(i=0; i='A' && c<='Z' ){ + zOut[i] = c - 'A' + 'a'; + }else{ + if( c>='0' && c<='9' ) hasDigit = 1; + zOut[i] = c; + } + } + mx = hasDigit ? 3 : 10; + if( nIn>mx*2 ){ + for(j=mx, i=nIn-mx; i=sizeof(zReverse)-7 ){ + /* The word is too big or too small for the porter stemmer. + ** Fallback to the copy stemmer */ + copy_stemmer(zIn, nIn, zOut, pnOut); + return; + } + for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ + zReverse[j] = c + 'a' - 'A'; + }else if( c>='a' && c<='z' ){ + zReverse[j] = c; + }else{ + /* The use of a character not in [a-zA-Z] means that we fallback + ** to the copy stemmer */ + copy_stemmer(zIn, nIn, zOut, pnOut); + return; + } + } + memset(&zReverse[sizeof(zReverse)-5], 0, 5); + z = &zReverse[j+1]; + + + /* Step 1a */ + if( z[0]=='s' ){ + if( + !stem(&z, "sess", "ss", 0) && + !stem(&z, "sei", "i", 0) && + !stem(&z, "ss", "ss", 0) + ){ + z++; + } + } + + /* Step 1b */ + z2 = z; + if( stem(&z, "dee", "ee", m_gt_0) ){ + /* Do nothing. The work was all in the test */ + }else if( + (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) + && z!=z2 + ){ + if( stem(&z, "ta", "ate", 0) || + stem(&z, "lb", "ble", 0) || + stem(&z, "zi", "ize", 0) ){ + /* Do nothing. The work was all in the test */ + }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ + z++; + }else if( m_eq_1(z) && star_oh(z) ){ + *(--z) = 'e'; + } + } + + /* Step 1c */ + if( z[0]=='y' && hasVowel(z+1) ){ + z[0] = 'i'; + } + + /* Step 2 */ + switch( z[1] ){ + case 'a': + stem(&z, "lanoita", "ate", m_gt_0) || + stem(&z, "lanoit", "tion", m_gt_0); + break; + case 'c': + stem(&z, "icne", "ence", m_gt_0) || + stem(&z, "icna", "ance", m_gt_0); + break; + case 'e': + stem(&z, "rezi", "ize", m_gt_0); + break; + case 'g': + stem(&z, "igol", "log", m_gt_0); + break; + case 'l': + stem(&z, "ilb", "ble", m_gt_0) || + stem(&z, "illa", "al", m_gt_0) || + stem(&z, "iltne", "ent", m_gt_0) || + stem(&z, "ile", "e", m_gt_0) || + stem(&z, "ilsuo", "ous", m_gt_0); + break; + case 'o': + stem(&z, "noitazi", "ize", m_gt_0) || + stem(&z, "noita", "ate", m_gt_0) || + stem(&z, "rota", "ate", m_gt_0); + break; + case 's': + stem(&z, "msila", "al", m_gt_0) || + stem(&z, "ssenevi", "ive", m_gt_0) || + stem(&z, "ssenluf", "ful", m_gt_0) || + stem(&z, "ssensuo", "ous", m_gt_0); + break; + case 't': + stem(&z, "itila", "al", m_gt_0) || + stem(&z, "itivi", "ive", m_gt_0) || + stem(&z, "itilib", "ble", m_gt_0); + break; + } + + /* Step 3 */ + switch( z[0] ){ + case 'e': + stem(&z, "etaci", "ic", m_gt_0) || + stem(&z, "evita", "", m_gt_0) || + stem(&z, "ezila", "al", m_gt_0); + break; + case 'i': + stem(&z, "itici", "ic", m_gt_0); + break; + case 'l': + stem(&z, "laci", "ic", m_gt_0) || + stem(&z, "luf", "", m_gt_0); + break; + case 's': + stem(&z, "ssen", "", m_gt_0); + break; + } + + /* Step 4 */ + switch( z[1] ){ + case 'a': + if( z[0]=='l' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'c': + if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ + z += 4; + } + break; + case 'e': + if( z[0]=='r' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'i': + if( z[0]=='c' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'l': + if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ + z += 4; + } + break; + case 'n': + if( z[0]=='t' ){ + if( z[2]=='a' ){ + if( m_gt_1(z+3) ){ + z += 3; + } + }else if( z[2]=='e' ){ + stem(&z, "tneme", "", m_gt_1) || + stem(&z, "tnem", "", m_gt_1) || + stem(&z, "tne", "", m_gt_1); + } + } + break; + case 'o': + if( z[0]=='u' ){ + if( m_gt_1(z+2) ){ + z += 2; + } + }else if( z[3]=='s' || z[3]=='t' ){ + stem(&z, "noi", "", m_gt_1); + } + break; + case 's': + if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ + z += 3; + } + break; + case 't': + stem(&z, "eta", "", m_gt_1) || + stem(&z, "iti", "", m_gt_1); + break; + case 'u': + if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ + z += 3; + } + break; + case 'v': + case 'z': + if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ + z += 3; + } + break; + } + + /* Step 5a */ + if( z[0]=='e' ){ + if( m_gt_1(z+1) ){ + z++; + }else if( m_eq_1(z+1) && !star_oh(z+1) ){ + z++; + } + } + + /* Step 5b */ + if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ + z++; + } + + /* z[] is now the stemmed word in reverse order. Flip it back + ** around into forward order and return. + */ + *pnOut = i = strlen(z); + zOut[i] = 0; + while( *z ){ + zOut[--i] = *(z++); + } +} + +/* +** Characters that can be part of a token. We assume any character +** whose value is greater than 0x80 (any UTF character) can be +** part of a token. In other words, delimiters all must have +** values of 0x7f or lower. +*/ +static const char porterIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30])) + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to porterOpen(). +*/ +static int porterNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ + const char **pzToken, /* OUT: *pzToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; + const char *z = c->zInput; + + while( c->iOffsetnInput ){ + int iStartOffset, ch; + + /* Scan past delimiter characters */ + while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ + c->iOffset++; + } + + /* Count non-delimiter characters. */ + iStartOffset = c->iOffset; + while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ + c->iOffset++; + } + + if( c->iOffset>iStartOffset ){ + int n = c->iOffset-iStartOffset; + if( n>c->nAllocated ){ + c->nAllocated = n+20; + c->zToken = realloc(c->zToken, c->nAllocated); + if( c->zToken==NULL ) return SQLITE_NOMEM; + } + porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); + *pzToken = c->zToken; + *piStartOffset = iStartOffset; + *piEndOffset = c->iOffset; + *piPosition = c->iToken++; + return SQLITE_OK; + } + } + return SQLITE_DONE; +} + +/* +** The set of routines that implement the porter-stemmer tokenizer +*/ +static const sqlite3_tokenizer_module porterTokenizerModule = { + 0, + porterCreate, + porterDestroy, + porterOpen, + porterClose, + porterNext, +}; + +/* +** Allocate a new porter tokenizer. Return a pointer to the new +** tokenizer in *ppModule +*/ +void sqlite3Fts2PorterTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &porterTokenizerModule; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.c new file mode 100644 index 0000000..cbf771b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.c @@ -0,0 +1,371 @@ +/* +** 2007 June 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 is part of an SQLite module implementing full-text search. +** This particular file implements the generic tokenizer interface. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS2 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS2 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) + + +#include "sqlite3.h" +#include "sqlite3ext.h" +SQLITE_EXTENSION_INIT1 + +#include "fts2_hash.h" +#include "fts2_tokenizer.h" +#include + +/* +** Implementation of the SQL scalar function for accessing the underlying +** hash table. This function may be called as follows: +** +** SELECT (); +** SELECT (, ); +** +** where is the name passed as the second argument +** to the sqlite3Fts2InitHashTable() function (e.g. 'fts2_tokenizer'). +** +** If the argument is specified, it must be a blob value +** containing a pointer to be stored as the hash data corresponding +** to the string . If is not specified, then +** the string must already exist in the has table. Otherwise, +** an error is returned. +** +** Whether or not the argument is specified, the value returned +** is a blob containing the pointer stored as the hash data corresponding +** to string (after the hash-table is updated, if applicable). +*/ +static void scalarFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts2Hash *pHash; + void *pPtr = 0; + const unsigned char *zName; + int nName; + + assert( argc==1 || argc==2 ); + + pHash = (fts2Hash *)sqlite3_user_data(context); + + zName = sqlite3_value_text(argv[0]); + nName = sqlite3_value_bytes(argv[0])+1; + + if( argc==2 ){ + void *pOld; + int n = sqlite3_value_bytes(argv[1]); + if( n!=sizeof(pPtr) ){ + sqlite3_result_error(context, "argument type mismatch", -1); + return; + } + pPtr = *(void **)sqlite3_value_blob(argv[1]); + pOld = sqlite3Fts2HashInsert(pHash, (void *)zName, nName, pPtr); + if( pOld==pPtr ){ + sqlite3_result_error(context, "out of memory", -1); + return; + } + }else{ + pPtr = sqlite3Fts2HashFind(pHash, zName, nName); + if( !pPtr ){ + char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + } + + sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); +} + +#ifdef SQLITE_TEST + +#include +#include + +/* +** Implementation of a special SQL scalar function for testing tokenizers +** designed to be used in concert with the Tcl testing framework. This +** function must be called with two arguments: +** +** SELECT (, ); +** SELECT (, ); +** +** where is the name passed as the second argument +** to the sqlite3Fts2InitHashTable() function (e.g. 'fts2_tokenizer') +** concatenated with the string '_test' (e.g. 'fts2_tokenizer_test'). +** +** The return value is a string that may be interpreted as a Tcl +** list. For each token in the , three elements are +** added to the returned list. The first is the token position, the +** second is the token text (folded, stemmed, etc.) and the third is the +** substring of associated with the token. For example, +** using the built-in "simple" tokenizer: +** +** SELECT fts_tokenizer_test('simple', 'I don't see how'); +** +** will return the string: +** +** "{0 i I 1 dont don't 2 see see 3 how how}" +** +*/ +static void testFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts2Hash *pHash; + sqlite3_tokenizer_module *p; + sqlite3_tokenizer *pTokenizer = 0; + sqlite3_tokenizer_cursor *pCsr = 0; + + const char *zErr = 0; + + const char *zName; + int nName; + const char *zInput; + int nInput; + + const char *zArg = 0; + + const char *zToken; + int nToken; + int iStart; + int iEnd; + int iPos; + + Tcl_Obj *pRet; + + assert( argc==2 || argc==3 ); + + nName = sqlite3_value_bytes(argv[0]); + zName = (const char *)sqlite3_value_text(argv[0]); + nInput = sqlite3_value_bytes(argv[argc-1]); + zInput = (const char *)sqlite3_value_text(argv[argc-1]); + + if( argc==3 ){ + zArg = (const char *)sqlite3_value_text(argv[1]); + } + + pHash = (fts2Hash *)sqlite3_user_data(context); + p = (sqlite3_tokenizer_module *)sqlite3Fts2HashFind(pHash, zName, nName+1); + + if( !p ){ + char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + + pRet = Tcl_NewObj(); + Tcl_IncrRefCount(pRet); + + if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ + zErr = "error in xCreate()"; + goto finish; + } + pTokenizer->pModule = p; + if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){ + zErr = "error in xOpen()"; + goto finish; + } + pCsr->pTokenizer = pTokenizer; + + while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); + zToken = &zInput[iStart]; + nToken = iEnd-iStart; + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); + } + + if( SQLITE_OK!=p->xClose(pCsr) ){ + zErr = "error in xClose()"; + goto finish; + } + if( SQLITE_OK!=p->xDestroy(pTokenizer) ){ + zErr = "error in xDestroy()"; + goto finish; + } + +finish: + if( zErr ){ + sqlite3_result_error(context, zErr, -1); + }else{ + sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); + } + Tcl_DecrRefCount(pRet); +} + +static +int registerTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module *p +){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts2_tokenizer(?, ?)"; + + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); + sqlite3_step(pStmt); + + return sqlite3_finalize(pStmt); +} + +static +int queryTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module **pp +){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts2_tokenizer(?)"; + + *pp = 0; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ + memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); + } + } + + return sqlite3_finalize(pStmt); +} + +void sqlite3Fts2SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); + +/* +** Implementation of the scalar function fts2_tokenizer_internal_test(). +** This function is used for testing only, it is not included in the +** build unless SQLITE_TEST is defined. +** +** The purpose of this is to test that the fts2_tokenizer() function +** can be used as designed by the C-code in the queryTokenizer and +** registerTokenizer() functions above. These two functions are repeated +** in the README.tokenizer file as an example, so it is important to +** test them. +** +** To run the tests, evaluate the fts2_tokenizer_internal_test() scalar +** function with no arguments. An assert() will fail if a problem is +** detected. i.e.: +** +** SELECT fts2_tokenizer_internal_test(); +** +*/ +static void intTestFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int rc; + const sqlite3_tokenizer_module *p1; + const sqlite3_tokenizer_module *p2; + sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); + + /* Test the query function */ + sqlite3Fts2SimpleTokenizerModule(&p1); + rc = queryTokenizer(db, "simple", &p2); + assert( rc==SQLITE_OK ); + assert( p1==p2 ); + rc = queryTokenizer(db, "nosuchtokenizer", &p2); + assert( rc==SQLITE_ERROR ); + assert( p2==0 ); + assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); + + /* Test the storage function */ + rc = registerTokenizer(db, "nosuchtokenizer", p1); + assert( rc==SQLITE_OK ); + rc = queryTokenizer(db, "nosuchtokenizer", &p2); + assert( rc==SQLITE_OK ); + assert( p2==p1 ); + + sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); +} + +#endif + +/* +** Set up SQL objects in database db used to access the contents of +** the hash table pointed to by argument pHash. The hash table must +** been initialised to use string keys, and to take a private copy +** of the key when a value is inserted. i.e. by a call similar to: +** +** sqlite3Fts2HashInit(pHash, FTS2_HASH_STRING, 1); +** +** This function adds a scalar function (see header comment above +** scalarFunc() in this file for details) and, if ENABLE_TABLE is +** defined at compilation time, a temporary virtual table (see header +** comment above struct HashTableVtab) to the database schema. Both +** provide read/write access to the contents of *pHash. +** +** The third argument to this function, zName, is used as the name +** of both the scalar and, if created, the virtual table. +*/ +int sqlite3Fts2InitHashTable( + sqlite3 *db, + fts2Hash *pHash, + const char *zName +){ + int rc = SQLITE_OK; + void *p = (void *)pHash; + const int any = SQLITE_ANY; + char *zTest = 0; + char *zTest2 = 0; + +#ifdef SQLITE_TEST + void *pdb = (void *)db; + zTest = sqlite3_mprintf("%s_test", zName); + zTest2 = sqlite3_mprintf("%s_internal_test", zName); + if( !zTest || !zTest2 ){ + rc = SQLITE_NOMEM; + } +#endif + + if( rc!=SQLITE_OK + || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) + || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) +#ifdef SQLITE_TEST + || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) + || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) + || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) +#endif + ); + + sqlite3_free(zTest); + sqlite3_free(zTest2); + return rc; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.h new file mode 100644 index 0000000..8c256b2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer.h @@ -0,0 +1,145 @@ +/* +** 2006 July 10 +** +** The author disclaims copyright to this source code. +** +************************************************************************* +** Defines the interface to tokenizers used by fulltext-search. There +** are three basic components: +** +** sqlite3_tokenizer_module is a singleton defining the tokenizer +** interface functions. This is essentially the class structure for +** tokenizers. +** +** sqlite3_tokenizer is used to define a particular tokenizer, perhaps +** including customization information defined at creation time. +** +** sqlite3_tokenizer_cursor is generated by a tokenizer to generate +** tokens from a particular input. +*/ +#ifndef _FTS2_TOKENIZER_H_ +#define _FTS2_TOKENIZER_H_ + +/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. +** If tokenizers are to be allowed to call sqlite3_*() functions, then +** we will need a way to register the API consistently. +*/ +#include "sqlite3.h" + +/* +** Structures used by the tokenizer interface. When a new tokenizer +** implementation is registered, the caller provides a pointer to +** an sqlite3_tokenizer_module containing pointers to the callback +** functions that make up an implementation. +** +** When an fts2 table is created, it passes any arguments passed to +** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the +** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer +** implementation. The xCreate() function in turn returns an +** sqlite3_tokenizer structure representing the specific tokenizer to +** be used for the fts2 table (customized by the tokenizer clause arguments). +** +** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() +** method is called. It returns an sqlite3_tokenizer_cursor object +** that may be used to tokenize a specific input buffer based on +** the tokenization rules supplied by a specific sqlite3_tokenizer +** object. +*/ +typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; +typedef struct sqlite3_tokenizer sqlite3_tokenizer; +typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; + +struct sqlite3_tokenizer_module { + + /* + ** Structure version. Should always be set to 0. + */ + int iVersion; + + /* + ** Create a new tokenizer. The values in the argv[] array are the + ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL + ** TABLE statement that created the fts2 table. For example, if + ** the following SQL is executed: + ** + ** CREATE .. USING fts2( ... , tokenizer arg1 arg2) + ** + ** then argc is set to 2, and the argv[] array contains pointers + ** to the strings "arg1" and "arg2". + ** + ** This method should return either SQLITE_OK (0), or an SQLite error + ** code. If SQLITE_OK is returned, then *ppTokenizer should be set + ** to point at the newly created tokenizer structure. The generic + ** sqlite3_tokenizer.pModule variable should not be initialised by + ** this callback. The caller will do so. + */ + int (*xCreate)( + int argc, /* Size of argv array */ + const char *const*argv, /* Tokenizer argument strings */ + sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ + ); + + /* + ** Destroy an existing tokenizer. The fts2 module calls this method + ** exactly once for each successful call to xCreate(). + */ + int (*xDestroy)(sqlite3_tokenizer *pTokenizer); + + /* + ** Create a tokenizer cursor to tokenize an input buffer. The caller + ** is responsible for ensuring that the input buffer remains valid + ** until the cursor is closed (using the xClose() method). + */ + int (*xOpen)( + sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ + const char *pInput, int nBytes, /* Input buffer */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ + ); + + /* + ** Destroy an existing tokenizer cursor. The fts2 module calls this + ** method exactly once for each successful call to xOpen(). + */ + int (*xClose)(sqlite3_tokenizer_cursor *pCursor); + + /* + ** Retrieve the next token from the tokenizer cursor pCursor. This + ** method should either return SQLITE_OK and set the values of the + ** "OUT" variables identified below, or SQLITE_DONE to indicate that + ** the end of the buffer has been reached, or an SQLite error code. + ** + ** *ppToken should be set to point at a buffer containing the + ** normalized version of the token (i.e. after any case-folding and/or + ** stemming has been performed). *pnBytes should be set to the length + ** of this buffer in bytes. The input text that generated the token is + ** identified by the byte offsets returned in *piStartOffset and + ** *piEndOffset. + ** + ** The buffer *ppToken is set to point at is managed by the tokenizer + ** implementation. It is only required to be valid until the next call + ** to xNext() or xClose(). + */ + /* TODO(shess) current implementation requires pInput to be + ** nul-terminated. This should either be fixed, or pInput/nBytes + ** should be converted to zInput. + */ + int (*xNext)( + sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ + const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ + int *piStartOffset, /* OUT: Byte offset of token in input buffer */ + int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ + int *piPosition /* OUT: Number of tokens returned before this one */ + ); +}; + +struct sqlite3_tokenizer { + const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ + /* Tokenizer implementations will typically add additional fields */ +}; + +struct sqlite3_tokenizer_cursor { + sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ + /* Tokenizer implementations will typically add additional fields */ +}; + +#endif /* _FTS2_TOKENIZER_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer1.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer1.c new file mode 100644 index 0000000..540ba27 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/fts2_tokenizer1.c @@ -0,0 +1,229 @@ +/* +** 2006 Oct 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. +** +****************************************************************************** +** +** Implementation of the "simple" full-text-search tokenizer. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS2 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS2 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS2 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) + + +#include +#include +#include +#include +#include + +#include "fts2_tokenizer.h" + +typedef struct simple_tokenizer { + sqlite3_tokenizer base; + char delim[128]; /* flag ASCII delimiters */ +} simple_tokenizer; + +typedef struct simple_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *pInput; /* input we are tokenizing */ + int nBytes; /* size of the input */ + int iOffset; /* current position in pInput */ + int iToken; /* index of next token to be returned */ + char *pToken; /* storage for current token */ + int nTokenAllocated; /* space allocated to zToken buffer */ +} simple_tokenizer_cursor; + + +/* Forward declaration */ +static const sqlite3_tokenizer_module simpleTokenizerModule; + +static int simpleDelim(simple_tokenizer *t, unsigned char c){ + return c<0x80 && t->delim[c]; +} + +/* +** Create a new tokenizer instance. +*/ +static int simpleCreate( + int argc, const char * const *argv, + sqlite3_tokenizer **ppTokenizer +){ + simple_tokenizer *t; + + t = (simple_tokenizer *) calloc(sizeof(*t), 1); + if( t==NULL ) return SQLITE_NOMEM; + + /* TODO(shess) Delimiters need to remain the same from run to run, + ** else we need to reindex. One solution would be a meta-table to + ** track such information in the database, then we'd only want this + ** information on the initial create. + */ + if( argc>1 ){ + int i, n = strlen(argv[1]); + for(i=0; i=0x80 ){ + free(t); + return SQLITE_ERROR; + } + t->delim[ch] = 1; + } + } else { + /* Mark non-alphanumeric ASCII characters as delimiters */ + int i; + for(i=1; i<0x80; i++){ + t->delim[i] = !isalnum(i); + } + } + + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ + free(pTokenizer); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is pInput[0..nBytes-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int simpleOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *pInput, int nBytes, /* String to be tokenized */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + simple_tokenizer_cursor *c; + + c = (simple_tokenizer_cursor *) malloc(sizeof(*c)); + if( c==NULL ) return SQLITE_NOMEM; + + c->pInput = pInput; + if( pInput==0 ){ + c->nBytes = 0; + }else if( nBytes<0 ){ + c->nBytes = (int)strlen(pInput); + }else{ + c->nBytes = nBytes; + } + c->iOffset = 0; /* start tokenizing at the beginning */ + c->iToken = 0; + c->pToken = NULL; /* no space allocated, yet. */ + c->nTokenAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** simpleOpen() above. +*/ +static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + free(c->pToken); + free(c); + return SQLITE_OK; +} + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to simpleOpen(). +*/ +static int simpleNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ + const char **ppToken, /* OUT: *ppToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; + unsigned char *p = (unsigned char *)c->pInput; + + while( c->iOffsetnBytes ){ + int iStartOffset; + + /* Scan past delimiter characters */ + while( c->iOffsetnBytes && simpleDelim(t, p[c->iOffset]) ){ + c->iOffset++; + } + + /* Count non-delimiter characters. */ + iStartOffset = c->iOffset; + while( c->iOffsetnBytes && !simpleDelim(t, p[c->iOffset]) ){ + c->iOffset++; + } + + if( c->iOffset>iStartOffset ){ + int i, n = c->iOffset-iStartOffset; + if( n>c->nTokenAllocated ){ + c->nTokenAllocated = n+20; + c->pToken = realloc(c->pToken, c->nTokenAllocated); + if( c->pToken==NULL ) return SQLITE_NOMEM; + } + for(i=0; ipToken[i] = ch<0x80 ? tolower(ch) : ch; + } + *ppToken = c->pToken; + *pnBytes = n; + *piStartOffset = iStartOffset; + *piEndOffset = c->iOffset; + *piPosition = c->iToken++; + + return SQLITE_OK; + } + } + return SQLITE_DONE; +} + +/* +** The set of routines that implement the simple tokenizer +*/ +static const sqlite3_tokenizer_module simpleTokenizerModule = { + 0, + simpleCreate, + simpleDestroy, + simpleOpen, + simpleClose, + simpleNext, +}; + +/* +** Allocate a new simple tokenizer. Return a pointer to the new +** tokenizer in *ppModule +*/ +void sqlite3Fts2SimpleTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &simpleTokenizerModule; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS2) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts2/mkfts2amal.tcl b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/mkfts2amal.tcl new file mode 100644 index 0000000..5c8d1e9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts2/mkfts2amal.tcl @@ -0,0 +1,116 @@ +#!/usr/bin/tclsh +# +# This script builds a single C code file holding all of FTS2 code. +# The name of the output file is fts2amal.c. To build this file, +# first do: +# +# make target_source +# +# The make target above moves all of the source code files into +# a subdirectory named "tsrc". (This script expects to find the files +# there and will not work if they are not found.) +# +# After the "tsrc" directory has been created and populated, run +# this script: +# +# tclsh mkfts2amal.tcl +# +# The amalgamated FTS2 code will be written into fts2amal.c +# + +# Open the output file and write a header comment at the beginning +# of the file. +# +set out [open fts2amal.c w] +set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] +puts $out [subst \ +{/****************************************************************************** +** This file is an amalgamation of separate C source files from the SQLite +** Full Text Search extension 2 (fts2). By combining all the individual C +** code files into this single large file, the entire code can be compiled +** as a one translation unit. This allows many compilers to do optimizations +** that would not be possible if the files were compiled separately. It also +** makes the code easier to import into other projects. +** +** This amalgamation was generated on $today. +*/}] + +# These are the header files used by FTS2. The first time any of these +# files are seen in a #include statement in the C code, include the complete +# text of the file in-line. The file only needs to be included once. +# +foreach hdr { + fts2.h + fts2_hash.h + fts2_tokenizer.h + sqlite3.h + sqlite3ext.h +} { + set available_hdr($hdr) 1 +} + +# 78 stars used for comment formatting. +set s78 \ +{*****************************************************************************} + +# Insert a comment into the code +# +proc section_comment {text} { + global out s78 + set n [string length $text] + set nstar [expr {60 - $n}] + set stars [string range $s78 0 $nstar] + puts $out "/************** $text $stars/" +} + +# Read the source file named $filename and write it into the +# sqlite3.c output file. If any #include statements are seen, +# process them approprately. +# +proc copy_file {filename} { + global seen_hdr available_hdr out + set tail [file tail $filename] + section_comment "Begin file $tail" + set in [open $filename r] + while {![eof $in]} { + set line [gets $in] + if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} { + if {[info exists available_hdr($hdr)]} { + if {$available_hdr($hdr)} { + section_comment "Include $hdr in the middle of $tail" + copy_file tsrc/$hdr + section_comment "Continuing where we left off in $tail" + } + } elseif {![info exists seen_hdr($hdr)]} { + set seen_hdr($hdr) 1 + puts $out $line + } + } elseif {[regexp {^#ifdef __cplusplus} $line]} { + puts $out "#if 0" + } elseif {[regexp {^#line} $line]} { + # Skip #line directives. + } else { + puts $out $line + } + } + close $in + section_comment "End of $tail" +} + + +# Process the source files. Process files containing commonly +# used subroutines first in order to help the compiler find +# inlining opportunities. +# +foreach file { + fts2.c + fts2_hash.c + fts2_porter.c + fts2_tokenizer.c + fts2_tokenizer1.c + fts2_icu.c +} { + copy_file tsrc/$file +} + +close $out diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Entries b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Entries new file mode 100644 index 0000000..65354a8 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Entries @@ -0,0 +1,13 @@ +/README.txt/1.1/Mon Aug 20 17:37:03 2007// +/fts3.h/1.1/Mon Aug 20 17:37:04 2007// +/fts3_hash.c/1.4/Sat Nov 24 00:41:52 2007// +/fts3_hash.h/1.2/Thu Sep 20 12:53:28 2007// +/fts3_icu.c/1.2/Wed Oct 24 21:52:37 2007// +/fts3_tokenizer.h/1.1/Mon Aug 20 17:37:04 2007// +/fts3_tokenizer1.c/1.2/Fri Nov 23 17:31:18 2007// +/README.tokenizers/1.2/Thu Dec 13 21:44:26 2007// +/mkfts3amal.tcl/1.2/Thu Jan 31 12:32:59 2008// +/fts3_porter.c/1.2/Fri Feb 1 15:40:34 2008// +/fts3.c/1.15/Sat Feb 2 16:24:34 2008// +/fts3_tokenizer.c/1.3/Sat Feb 2 16:24:34 2008// +D diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Repository b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Repository new file mode 100644 index 0000000..e8a6ccd --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Repository @@ -0,0 +1 @@ +sqlite/ext/fts3 diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Root b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Root new file mode 100644 index 0000000..a3ae5d0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/CVS/Root @@ -0,0 +1 @@ +:pserver:drh@sqlite.org:/sqlite diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.tokenizers b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.tokenizers new file mode 100644 index 0000000..83d2f9d --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.tokenizers @@ -0,0 +1,133 @@ + +1. FTS3 Tokenizers + + When creating a new full-text table, FTS3 allows the user to select + the text tokenizer implementation to be used when indexing text + by specifying a "tokenizer" clause as part of the CREATE VIRTUAL TABLE + statement: + + CREATE VIRTUAL TABLE USING fts3( + [, tokenizer []] + ); + + The built-in tokenizers (valid values to pass as ) are + "simple" and "porter". + + should consist of zero or more white-space separated + arguments to pass to the selected tokenizer implementation. The + interpretation of the arguments, if any, depends on the individual + tokenizer. + +2. Custom Tokenizers + + FTS3 allows users to provide custom tokenizer implementations. The + interface used to create a new tokenizer is defined and described in + the fts3_tokenizer.h source file. + + Registering a new FTS3 tokenizer is similar to registering a new + virtual table module with SQLite. The user passes a pointer to a + structure containing pointers to various callback functions that + make up the implementation of the new tokenizer type. For tokenizers, + the structure (defined in fts3_tokenizer.h) is called + "sqlite3_tokenizer_module". + + FTS3 does not expose a C-function that users call to register new + tokenizer types with a database handle. Instead, the pointer must + be encoded as an SQL blob value and passed to FTS3 through the SQL + engine by evaluating a special scalar function, "fts3_tokenizer()". + The fts3_tokenizer() function may be called with one or two arguments, + as follows: + + SELECT fts3_tokenizer(); + SELECT fts3_tokenizer(, ); + + Where is a string identifying the tokenizer and + is a pointer to an sqlite3_tokenizer_module + structure encoded as an SQL blob. If the second argument is present, + it is registered as tokenizer and a copy of it + returned. If only one argument is passed, a pointer to the tokenizer + implementation currently registered as is returned, + encoded as a blob. Or, if no such tokenizer exists, an SQL exception + (error) is raised. + + SECURITY: If the fts3 extension is used in an environment where potentially + malicious users may execute arbitrary SQL (i.e. gears), they should be + prevented from invoking the fts3_tokenizer() function, possibly using the + authorisation callback. + + See "Sample code" below for an example of calling the fts3_tokenizer() + function from C code. + +3. ICU Library Tokenizers + + If this extension is compiled with the SQLITE_ENABLE_ICU pre-processor + symbol defined, then there exists a built-in tokenizer named "icu" + implemented using the ICU library. The first argument passed to the + xCreate() method (see fts3_tokenizer.h) of this tokenizer may be + an ICU locale identifier. For example "tr_TR" for Turkish as used + in Turkey, or "en_AU" for English as used in Australia. For example: + + "CREATE VIRTUAL TABLE thai_text USING fts3(text, tokenizer icu th_TH)" + + The ICU tokenizer implementation is very simple. It splits the input + text according to the ICU rules for finding word boundaries and discards + any tokens that consist entirely of white-space. This may be suitable + for some applications in some locales, but not all. If more complex + processing is required, for example to implement stemming or + discard punctuation, this can be done by creating a tokenizer + implementation that uses the ICU tokenizer as part of its implementation. + + When using the ICU tokenizer this way, it is safe to overwrite the + contents of the strings returned by the xNext() method (see + fts3_tokenizer.h). + +4. Sample code. + + The following two code samples illustrate the way C code should invoke + the fts3_tokenizer() scalar function: + + int registerTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module *p + ){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; + + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); + sqlite3_step(pStmt); + + return sqlite3_finalize(pStmt); + } + + int queryTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module **pp + ){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts3_tokenizer(?)"; + + *pp = 0; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ + memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); + } + } + + return sqlite3_finalize(pStmt); + } diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.txt b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.txt new file mode 100644 index 0000000..517a2a0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/README.txt @@ -0,0 +1,4 @@ +This folder contains source code to the second full-text search +extension for SQLite. While the API is the same, this version uses a +substantially different storage schema from fts1, so tables will need +to be rebuilt. diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.c new file mode 100644 index 0000000..2aaeb11 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.c @@ -0,0 +1,6403 @@ +/* +** 2006 Oct 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. +** +****************************************************************************** +** +** This is an SQLite module implementing full-text search. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS3 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS3 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). +*/ + +/* TODO(shess) Consider exporting this comment to an HTML file or the +** wiki. +*/ +/* The full-text index is stored in a series of b+tree (-like) +** structures called segments which map terms to doclists. The +** structures are like b+trees in layout, but are constructed from the +** bottom up in optimal fashion and are not updatable. Since trees +** are built from the bottom up, things will be described from the +** bottom up. +** +** +**** Varints **** +** The basic unit of encoding is a variable-length integer called a +** varint. We encode variable-length integers in little-endian order +** using seven bits * per byte as follows: +** +** KEY: +** A = 0xxxxxxx 7 bits of data and one flag bit +** B = 1xxxxxxx 7 bits of data and one flag bit +** +** 7 bits - A +** 14 bits - BA +** 21 bits - BBA +** and so on. +** +** This is identical to how sqlite encodes varints (see util.c). +** +** +**** Document lists **** +** A doclist (document list) holds a docid-sorted list of hits for a +** given term. Doclists hold docids, and can optionally associate +** token positions and offsets with docids. +** +** A DL_POSITIONS_OFFSETS doclist is stored like this: +** +** array { +** varint docid; +** array { (position list for column 0) +** varint position; (delta from previous position plus POS_BASE) +** varint startOffset; (delta from previous startOffset) +** varint endOffset; (delta from startOffset) +** } +** array { +** varint POS_COLUMN; (marks start of position list for new column) +** varint column; (index of new column) +** array { +** varint position; (delta from previous position plus POS_BASE) +** varint startOffset;(delta from previous startOffset) +** varint endOffset; (delta from startOffset) +** } +** } +** varint POS_END; (marks end of positions for this document. +** } +** +** Here, array { X } means zero or more occurrences of X, adjacent in +** memory. A "position" is an index of a token in the token stream +** generated by the tokenizer, while an "offset" is a byte offset, +** both based at 0. Note that POS_END and POS_COLUMN occur in the +** same logical place as the position element, and act as sentinals +** ending a position list array. +** +** A DL_POSITIONS doclist omits the startOffset and endOffset +** information. A DL_DOCIDS doclist omits both the position and +** offset information, becoming an array of varint-encoded docids. +** +** On-disk data is stored as type DL_DEFAULT, so we don't serialize +** the type. Due to how deletion is implemented in the segmentation +** system, on-disk doclists MUST store at least positions. +** +** +**** Segment leaf nodes **** +** Segment leaf nodes store terms and doclists, ordered by term. Leaf +** nodes are written using LeafWriter, and read using LeafReader (to +** iterate through a single leaf node's data) and LeavesReader (to +** iterate through a segment's entire leaf layer). Leaf nodes have +** the format: +** +** varint iHeight; (height from leaf level, always 0) +** varint nTerm; (length of first term) +** char pTerm[nTerm]; (content of first term) +** varint nDoclist; (length of term's associated doclist) +** char pDoclist[nDoclist]; (content of doclist) +** array { +** (further terms are delta-encoded) +** varint nPrefix; (length of prefix shared with previous term) +** varint nSuffix; (length of unshared suffix) +** char pTermSuffix[nSuffix];(unshared suffix of next term) +** varint nDoclist; (length of term's associated doclist) +** char pDoclist[nDoclist]; (content of doclist) +** } +** +** Here, array { X } means zero or more occurrences of X, adjacent in +** memory. +** +** Leaf nodes are broken into blocks which are stored contiguously in +** the %_segments table in sorted order. This means that when the end +** of a node is reached, the next term is in the node with the next +** greater node id. +** +** New data is spilled to a new leaf node when the current node +** exceeds LEAF_MAX bytes (default 2048). New data which itself is +** larger than STANDALONE_MIN (default 1024) is placed in a standalone +** node (a leaf node with a single term and doclist). The goal of +** these settings is to pack together groups of small doclists while +** making it efficient to directly access large doclists. The +** assumption is that large doclists represent terms which are more +** likely to be query targets. +** +** TODO(shess) It may be useful for blocking decisions to be more +** dynamic. For instance, it may make more sense to have a 2.5k leaf +** node rather than splitting into 2k and .5k nodes. My intuition is +** that this might extend through 2x or 4x the pagesize. +** +** +**** Segment interior nodes **** +** Segment interior nodes store blockids for subtree nodes and terms +** to describe what data is stored by the each subtree. Interior +** nodes are written using InteriorWriter, and read using +** InteriorReader. InteriorWriters are created as needed when +** SegmentWriter creates new leaf nodes, or when an interior node +** itself grows too big and must be split. The format of interior +** nodes: +** +** varint iHeight; (height from leaf level, always >0) +** varint iBlockid; (block id of node's leftmost subtree) +** optional { +** varint nTerm; (length of first term) +** char pTerm[nTerm]; (content of first term) +** array { +** (further terms are delta-encoded) +** varint nPrefix; (length of shared prefix with previous term) +** varint nSuffix; (length of unshared suffix) +** char pTermSuffix[nSuffix]; (unshared suffix of next term) +** } +** } +** +** Here, optional { X } means an optional element, while array { X } +** means zero or more occurrences of X, adjacent in memory. +** +** An interior node encodes n terms separating n+1 subtrees. The +** subtree blocks are contiguous, so only the first subtree's blockid +** is encoded. The subtree at iBlockid will contain all terms less +** than the first term encoded (or all terms if no term is encoded). +** Otherwise, for terms greater than or equal to pTerm[i] but less +** than pTerm[i+1], the subtree for that term will be rooted at +** iBlockid+i. Interior nodes only store enough term data to +** distinguish adjacent children (if the rightmost term of the left +** child is "something", and the leftmost term of the right child is +** "wicked", only "w" is stored). +** +** New data is spilled to a new interior node at the same height when +** the current node exceeds INTERIOR_MAX bytes (default 2048). +** INTERIOR_MIN_TERMS (default 7) keeps large terms from monopolizing +** interior nodes and making the tree too skinny. The interior nodes +** at a given height are naturally tracked by interior nodes at +** height+1, and so on. +** +** +**** Segment directory **** +** The segment directory in table %_segdir stores meta-information for +** merging and deleting segments, and also the root node of the +** segment's tree. +** +** The root node is the top node of the segment's tree after encoding +** the entire segment, restricted to ROOT_MAX bytes (default 1024). +** This could be either a leaf node or an interior node. If the top +** node requires more than ROOT_MAX bytes, it is flushed to %_segments +** and a new root interior node is generated (which should always fit +** within ROOT_MAX because it only needs space for 2 varints, the +** height and the blockid of the previous root). +** +** The meta-information in the segment directory is: +** level - segment level (see below) +** idx - index within level +** - (level,idx uniquely identify a segment) +** start_block - first leaf node +** leaves_end_block - last leaf node +** end_block - last block (including interior nodes) +** root - contents of root node +** +** If the root node is a leaf node, then start_block, +** leaves_end_block, and end_block are all 0. +** +** +**** Segment merging **** +** To amortize update costs, segments are groups into levels and +** merged in matches. Each increase in level represents exponentially +** more documents. +** +** New documents (actually, document updates) are tokenized and +** written individually (using LeafWriter) to a level 0 segment, with +** incrementing idx. When idx reaches MERGE_COUNT (default 16), all +** level 0 segments are merged into a single level 1 segment. Level 1 +** is populated like level 0, and eventually MERGE_COUNT level 1 +** segments are merged to a single level 2 segment (representing +** MERGE_COUNT^2 updates), and so on. +** +** A segment merge traverses all segments at a given level in +** parallel, performing a straightforward sorted merge. Since segment +** leaf nodes are written in to the %_segments table in order, this +** merge traverses the underlying sqlite disk structures efficiently. +** After the merge, all segment blocks from the merged level are +** deleted. +** +** MERGE_COUNT controls how often we merge segments. 16 seems to be +** somewhat of a sweet spot for insertion performance. 32 and 64 show +** very similar performance numbers to 16 on insertion, though they're +** a tiny bit slower (perhaps due to more overhead in merge-time +** sorting). 8 is about 20% slower than 16, 4 about 50% slower than +** 16, 2 about 66% slower than 16. +** +** At query time, high MERGE_COUNT increases the number of segments +** which need to be scanned and merged. For instance, with 100k docs +** inserted: +** +** MERGE_COUNT segments +** 16 25 +** 8 12 +** 4 10 +** 2 6 +** +** This appears to have only a moderate impact on queries for very +** frequent terms (which are somewhat dominated by segment merge +** costs), and infrequent and non-existent terms still seem to be fast +** even with many segments. +** +** TODO(shess) That said, it would be nice to have a better query-side +** argument for MERGE_COUNT of 16. Also, it is possible/likely that +** optimizations to things like doclist merging will swing the sweet +** spot around. +** +** +** +**** Handling of deletions and updates **** +** Since we're using a segmented structure, with no docid-oriented +** index into the term index, we clearly cannot simply update the term +** index when a document is deleted or updated. For deletions, we +** write an empty doclist (varint(docid) varint(POS_END)), for updates +** we simply write the new doclist. Segment merges overwrite older +** data for a particular docid with newer data, so deletes or updates +** will eventually overtake the earlier data and knock it out. The +** query logic likewise merges doclists so that newer data knocks out +** older data. +** +** TODO(shess) Provide a VACUUM type operation to clear out all +** deletions and duplications. This would basically be a forced merge +** into a single segment. +*/ + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) + +#if defined(SQLITE_ENABLE_FTS3) && !defined(SQLITE_CORE) +# define SQLITE_CORE 1 +#endif + +#include +#include +#include +#include +#include + +#include "fts3.h" +#include "fts3_hash.h" +#include "fts3_tokenizer.h" +#ifndef SQLITE_CORE +# include "sqlite3ext.h" + SQLITE_EXTENSION_INIT1 +#endif + + +/* TODO(shess) MAN, this thing needs some refactoring. At minimum, it +** would be nice to order the file better, perhaps something along the +** lines of: +** +** - utility functions +** - table setup functions +** - table update functions +** - table query functions +** +** Put the query functions last because they're likely to reference +** typedefs or functions from the table update section. +*/ + +#if 0 +# define FTSTRACE(A) printf A; fflush(stdout) +#else +# define FTSTRACE(A) +#endif + +/* +** Default span for NEAR operators. +*/ +#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10 + +/* It is not safe to call isspace(), tolower(), or isalnum() on +** hi-bit-set characters. This is the same solution used in the +** tokenizer. +*/ +/* TODO(shess) The snippet-generation code should be using the +** tokenizer-generated tokens rather than doing its own local +** tokenization. +*/ +/* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ +static int safe_isspace(char c){ + return (c&0x80)==0 ? isspace(c) : 0; +} +static int safe_tolower(char c){ + return (c&0x80)==0 ? tolower(c) : c; +} +static int safe_isalnum(char c){ + return (c&0x80)==0 ? isalnum(c) : 0; +} + +typedef enum DocListType { + DL_DOCIDS, /* docids only */ + DL_POSITIONS, /* docids + positions */ + DL_POSITIONS_OFFSETS /* docids + positions + offsets */ +} DocListType; + +/* +** By default, only positions and not offsets are stored in the doclists. +** To change this so that offsets are stored too, compile with +** +** -DDL_DEFAULT=DL_POSITIONS_OFFSETS +** +** If DL_DEFAULT is set to DL_DOCIDS, your table can only be inserted +** into (no deletes or updates). +*/ +#ifndef DL_DEFAULT +# define DL_DEFAULT DL_POSITIONS +#endif + +enum { + POS_END = 0, /* end of this position list */ + POS_COLUMN, /* followed by new column number */ + POS_BASE +}; + +/* MERGE_COUNT controls how often we merge segments (see comment at +** top of file). +*/ +#define MERGE_COUNT 16 + +/* utility functions */ + +/* CLEAR() and SCRAMBLE() abstract memset() on a pointer to a single +** record to prevent errors of the form: +** +** my_function(SomeType *b){ +** memset(b, '\0', sizeof(b)); // sizeof(b)!=sizeof(*b) +** } +*/ +/* TODO(shess) Obvious candidates for a header file. */ +#define CLEAR(b) memset(b, '\0', sizeof(*(b))) + +#ifndef NDEBUG +# define SCRAMBLE(b) memset(b, 0x55, sizeof(*(b))) +#else +# define SCRAMBLE(b) +#endif + +/* We may need up to VARINT_MAX bytes to store an encoded 64-bit integer. */ +#define VARINT_MAX 10 + +/* Write a 64-bit variable-length integer to memory starting at p[0]. + * The length of data written will be between 1 and VARINT_MAX bytes. + * The number of bytes written is returned. */ +static int fts3PutVarint(char *p, sqlite_int64 v){ + unsigned char *q = (unsigned char *) p; + sqlite_uint64 vu = v; + do{ + *q++ = (unsigned char) ((vu & 0x7f) | 0x80); + vu >>= 7; + }while( vu!=0 ); + q[-1] &= 0x7f; /* turn off high bit in final byte */ + assert( q - (unsigned char *)p <= VARINT_MAX ); + return (int) (q - (unsigned char *)p); +} + +/* Read a 64-bit variable-length integer from memory starting at p[0]. + * Return the number of bytes read, or 0 on error. + * The value is stored in *v. */ +static int fts3GetVarint(const char *p, sqlite_int64 *v){ + const unsigned char *q = (const unsigned char *) p; + sqlite_uint64 x = 0, y = 1; + while( (*q & 0x80) == 0x80 ){ + x += y * (*q++ & 0x7f); + y <<= 7; + if( q - (unsigned char *)p >= VARINT_MAX ){ /* bad data */ + assert( 0 ); + return 0; + } + } + x += y * (*q++); + *v = (sqlite_int64) x; + return (int) (q - (unsigned char *)p); +} + +static int fts3GetVarint32(const char *p, int *pi){ + sqlite_int64 i; + int ret = fts3GetVarint(p, &i); + *pi = (int) i; + assert( *pi==i ); + return ret; +} + +/*******************************************************************/ +/* DataBuffer is used to collect data into a buffer in piecemeal +** fashion. It implements the usual distinction between amount of +** data currently stored (nData) and buffer capacity (nCapacity). +** +** dataBufferInit - create a buffer with given initial capacity. +** dataBufferReset - forget buffer's data, retaining capacity. +** dataBufferDestroy - free buffer's data. +** dataBufferSwap - swap contents of two buffers. +** dataBufferExpand - expand capacity without adding data. +** dataBufferAppend - append data. +** dataBufferAppend2 - append two pieces of data at once. +** dataBufferReplace - replace buffer's data. +*/ +typedef struct DataBuffer { + char *pData; /* Pointer to malloc'ed buffer. */ + int nCapacity; /* Size of pData buffer. */ + int nData; /* End of data loaded into pData. */ +} DataBuffer; + +static void dataBufferInit(DataBuffer *pBuffer, int nCapacity){ + assert( nCapacity>=0 ); + pBuffer->nData = 0; + pBuffer->nCapacity = nCapacity; + pBuffer->pData = nCapacity==0 ? NULL : sqlite3_malloc(nCapacity); +} +static void dataBufferReset(DataBuffer *pBuffer){ + pBuffer->nData = 0; +} +static void dataBufferDestroy(DataBuffer *pBuffer){ + if( pBuffer->pData!=NULL ) sqlite3_free(pBuffer->pData); + SCRAMBLE(pBuffer); +} +static void dataBufferSwap(DataBuffer *pBuffer1, DataBuffer *pBuffer2){ + DataBuffer tmp = *pBuffer1; + *pBuffer1 = *pBuffer2; + *pBuffer2 = tmp; +} +static void dataBufferExpand(DataBuffer *pBuffer, int nAddCapacity){ + assert( nAddCapacity>0 ); + /* TODO(shess) Consider expanding more aggressively. Note that the + ** underlying malloc implementation may take care of such things for + ** us already. + */ + if( pBuffer->nData+nAddCapacity>pBuffer->nCapacity ){ + pBuffer->nCapacity = pBuffer->nData+nAddCapacity; + pBuffer->pData = sqlite3_realloc(pBuffer->pData, pBuffer->nCapacity); + } +} +static void dataBufferAppend(DataBuffer *pBuffer, + const char *pSource, int nSource){ + assert( nSource>0 && pSource!=NULL ); + dataBufferExpand(pBuffer, nSource); + memcpy(pBuffer->pData+pBuffer->nData, pSource, nSource); + pBuffer->nData += nSource; +} +static void dataBufferAppend2(DataBuffer *pBuffer, + const char *pSource1, int nSource1, + const char *pSource2, int nSource2){ + assert( nSource1>0 && pSource1!=NULL ); + assert( nSource2>0 && pSource2!=NULL ); + dataBufferExpand(pBuffer, nSource1+nSource2); + memcpy(pBuffer->pData+pBuffer->nData, pSource1, nSource1); + memcpy(pBuffer->pData+pBuffer->nData+nSource1, pSource2, nSource2); + pBuffer->nData += nSource1+nSource2; +} +static void dataBufferReplace(DataBuffer *pBuffer, + const char *pSource, int nSource){ + dataBufferReset(pBuffer); + dataBufferAppend(pBuffer, pSource, nSource); +} + +/* StringBuffer is a null-terminated version of DataBuffer. */ +typedef struct StringBuffer { + DataBuffer b; /* Includes null terminator. */ +} StringBuffer; + +static void initStringBuffer(StringBuffer *sb){ + dataBufferInit(&sb->b, 100); + dataBufferReplace(&sb->b, "", 1); +} +static int stringBufferLength(StringBuffer *sb){ + return sb->b.nData-1; +} +static char *stringBufferData(StringBuffer *sb){ + return sb->b.pData; +} +static void stringBufferDestroy(StringBuffer *sb){ + dataBufferDestroy(&sb->b); +} + +static void nappend(StringBuffer *sb, const char *zFrom, int nFrom){ + assert( sb->b.nData>0 ); + if( nFrom>0 ){ + sb->b.nData--; + dataBufferAppend2(&sb->b, zFrom, nFrom, "", 1); + } +} +static void append(StringBuffer *sb, const char *zFrom){ + nappend(sb, zFrom, strlen(zFrom)); +} + +/* Append a list of strings separated by commas. */ +static void appendList(StringBuffer *sb, int nString, char **azString){ + int i; + for(i=0; i0 ) append(sb, ", "); + append(sb, azString[i]); + } +} + +static int endsInWhiteSpace(StringBuffer *p){ + return stringBufferLength(p)>0 && + safe_isspace(stringBufferData(p)[stringBufferLength(p)-1]); +} + +/* If the StringBuffer ends in something other than white space, add a +** single space character to the end. +*/ +static void appendWhiteSpace(StringBuffer *p){ + if( stringBufferLength(p)==0 ) return; + if( !endsInWhiteSpace(p) ) append(p, " "); +} + +/* Remove white space from the end of the StringBuffer */ +static void trimWhiteSpace(StringBuffer *p){ + while( endsInWhiteSpace(p) ){ + p->b.pData[--p->b.nData-1] = '\0'; + } +} + +/*******************************************************************/ +/* DLReader is used to read document elements from a doclist. The +** current docid is cached, so dlrDocid() is fast. DLReader does not +** own the doclist buffer. +** +** dlrAtEnd - true if there's no more data to read. +** dlrDocid - docid of current document. +** dlrDocData - doclist data for current document (including docid). +** dlrDocDataBytes - length of same. +** dlrAllDataBytes - length of all remaining data. +** dlrPosData - position data for current document. +** dlrPosDataLen - length of pos data for current document (incl POS_END). +** dlrStep - step to current document. +** dlrInit - initial for doclist of given type against given data. +** dlrDestroy - clean up. +** +** Expected usage is something like: +** +** DLReader reader; +** dlrInit(&reader, pData, nData); +** while( !dlrAtEnd(&reader) ){ +** // calls to dlrDocid() and kin. +** dlrStep(&reader); +** } +** dlrDestroy(&reader); +*/ +typedef struct DLReader { + DocListType iType; + const char *pData; + int nData; + + sqlite_int64 iDocid; + int nElement; +} DLReader; + +static int dlrAtEnd(DLReader *pReader){ + assert( pReader->nData>=0 ); + return pReader->nData==0; +} +static sqlite_int64 dlrDocid(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->iDocid; +} +static const char *dlrDocData(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->pData; +} +static int dlrDocDataBytes(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->nElement; +} +static int dlrAllDataBytes(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + return pReader->nData; +} +/* TODO(shess) Consider adding a field to track iDocid varint length +** to make these two functions faster. This might matter (a tiny bit) +** for queries. +*/ +static const char *dlrPosData(DLReader *pReader){ + sqlite_int64 iDummy; + int n = fts3GetVarint(pReader->pData, &iDummy); + assert( !dlrAtEnd(pReader) ); + return pReader->pData+n; +} +static int dlrPosDataLen(DLReader *pReader){ + sqlite_int64 iDummy; + int n = fts3GetVarint(pReader->pData, &iDummy); + assert( !dlrAtEnd(pReader) ); + return pReader->nElement-n; +} +static void dlrStep(DLReader *pReader){ + assert( !dlrAtEnd(pReader) ); + + /* Skip past current doclist element. */ + assert( pReader->nElement<=pReader->nData ); + pReader->pData += pReader->nElement; + pReader->nData -= pReader->nElement; + + /* If there is more data, read the next doclist element. */ + if( pReader->nData!=0 ){ + sqlite_int64 iDocidDelta; + int iDummy, n = fts3GetVarint(pReader->pData, &iDocidDelta); + pReader->iDocid += iDocidDelta; + if( pReader->iType>=DL_POSITIONS ){ + assert( nnData ); + while( 1 ){ + n += fts3GetVarint32(pReader->pData+n, &iDummy); + assert( n<=pReader->nData ); + if( iDummy==POS_END ) break; + if( iDummy==POS_COLUMN ){ + n += fts3GetVarint32(pReader->pData+n, &iDummy); + assert( nnData ); + }else if( pReader->iType==DL_POSITIONS_OFFSETS ){ + n += fts3GetVarint32(pReader->pData+n, &iDummy); + n += fts3GetVarint32(pReader->pData+n, &iDummy); + assert( nnData ); + } + } + } + pReader->nElement = n; + assert( pReader->nElement<=pReader->nData ); + } +} +static void dlrInit(DLReader *pReader, DocListType iType, + const char *pData, int nData){ + assert( pData!=NULL && nData!=0 ); + pReader->iType = iType; + pReader->pData = pData; + pReader->nData = nData; + pReader->nElement = 0; + pReader->iDocid = 0; + + /* Load the first element's data. There must be a first element. */ + dlrStep(pReader); +} +static void dlrDestroy(DLReader *pReader){ + SCRAMBLE(pReader); +} + +#ifndef NDEBUG +/* Verify that the doclist can be validly decoded. Also returns the +** last docid found because it is convenient in other assertions for +** DLWriter. +*/ +static void docListValidate(DocListType iType, const char *pData, int nData, + sqlite_int64 *pLastDocid){ + sqlite_int64 iPrevDocid = 0; + assert( nData>0 ); + assert( pData!=0 ); + assert( pData+nData>pData ); + while( nData!=0 ){ + sqlite_int64 iDocidDelta; + int n = fts3GetVarint(pData, &iDocidDelta); + iPrevDocid += iDocidDelta; + if( iType>DL_DOCIDS ){ + int iDummy; + while( 1 ){ + n += fts3GetVarint32(pData+n, &iDummy); + if( iDummy==POS_END ) break; + if( iDummy==POS_COLUMN ){ + n += fts3GetVarint32(pData+n, &iDummy); + }else if( iType>DL_POSITIONS ){ + n += fts3GetVarint32(pData+n, &iDummy); + n += fts3GetVarint32(pData+n, &iDummy); + } + assert( n<=nData ); + } + } + assert( n<=nData ); + pData += n; + nData -= n; + } + if( pLastDocid ) *pLastDocid = iPrevDocid; +} +#define ASSERT_VALID_DOCLIST(i, p, n, o) docListValidate(i, p, n, o) +#else +#define ASSERT_VALID_DOCLIST(i, p, n, o) assert( 1 ) +#endif + +/*******************************************************************/ +/* DLWriter is used to write doclist data to a DataBuffer. DLWriter +** always appends to the buffer and does not own it. +** +** dlwInit - initialize to write a given type doclistto a buffer. +** dlwDestroy - clear the writer's memory. Does not free buffer. +** dlwAppend - append raw doclist data to buffer. +** dlwCopy - copy next doclist from reader to writer. +** dlwAdd - construct doclist element and append to buffer. +** Only apply dlwAdd() to DL_DOCIDS doclists (else use PLWriter). +*/ +typedef struct DLWriter { + DocListType iType; + DataBuffer *b; + sqlite_int64 iPrevDocid; +#ifndef NDEBUG + int has_iPrevDocid; +#endif +} DLWriter; + +static void dlwInit(DLWriter *pWriter, DocListType iType, DataBuffer *b){ + pWriter->b = b; + pWriter->iType = iType; + pWriter->iPrevDocid = 0; +#ifndef NDEBUG + pWriter->has_iPrevDocid = 0; +#endif +} +static void dlwDestroy(DLWriter *pWriter){ + SCRAMBLE(pWriter); +} +/* iFirstDocid is the first docid in the doclist in pData. It is +** needed because pData may point within a larger doclist, in which +** case the first item would be delta-encoded. +** +** iLastDocid is the final docid in the doclist in pData. It is +** needed to create the new iPrevDocid for future delta-encoding. The +** code could decode the passed doclist to recreate iLastDocid, but +** the only current user (docListMerge) already has decoded this +** information. +*/ +/* TODO(shess) This has become just a helper for docListMerge. +** Consider a refactor to make this cleaner. +*/ +static void dlwAppend(DLWriter *pWriter, + const char *pData, int nData, + sqlite_int64 iFirstDocid, sqlite_int64 iLastDocid){ + sqlite_int64 iDocid = 0; + char c[VARINT_MAX]; + int nFirstOld, nFirstNew; /* Old and new varint len of first docid. */ +#ifndef NDEBUG + sqlite_int64 iLastDocidDelta; +#endif + + /* Recode the initial docid as delta from iPrevDocid. */ + nFirstOld = fts3GetVarint(pData, &iDocid); + assert( nFirstOldiType==DL_DOCIDS) ); + nFirstNew = fts3PutVarint(c, iFirstDocid-pWriter->iPrevDocid); + + /* Verify that the incoming doclist is valid AND that it ends with + ** the expected docid. This is essential because we'll trust this + ** docid in future delta-encoding. + */ + ASSERT_VALID_DOCLIST(pWriter->iType, pData, nData, &iLastDocidDelta); + assert( iLastDocid==iFirstDocid-iDocid+iLastDocidDelta ); + + /* Append recoded initial docid and everything else. Rest of docids + ** should have been delta-encoded from previous initial docid. + */ + if( nFirstOldb, c, nFirstNew, + pData+nFirstOld, nData-nFirstOld); + }else{ + dataBufferAppend(pWriter->b, c, nFirstNew); + } + pWriter->iPrevDocid = iLastDocid; +} +static void dlwCopy(DLWriter *pWriter, DLReader *pReader){ + dlwAppend(pWriter, dlrDocData(pReader), dlrDocDataBytes(pReader), + dlrDocid(pReader), dlrDocid(pReader)); +} +static void dlwAdd(DLWriter *pWriter, sqlite_int64 iDocid){ + char c[VARINT_MAX]; + int n = fts3PutVarint(c, iDocid-pWriter->iPrevDocid); + + /* Docids must ascend. */ + assert( !pWriter->has_iPrevDocid || iDocid>pWriter->iPrevDocid ); + assert( pWriter->iType==DL_DOCIDS ); + + dataBufferAppend(pWriter->b, c, n); + pWriter->iPrevDocid = iDocid; +#ifndef NDEBUG + pWriter->has_iPrevDocid = 1; +#endif +} + +/*******************************************************************/ +/* PLReader is used to read data from a document's position list. As +** the caller steps through the list, data is cached so that varints +** only need to be decoded once. +** +** plrInit, plrDestroy - create/destroy a reader. +** plrColumn, plrPosition, plrStartOffset, plrEndOffset - accessors +** plrAtEnd - at end of stream, only call plrDestroy once true. +** plrStep - step to the next element. +*/ +typedef struct PLReader { + /* These refer to the next position's data. nData will reach 0 when + ** reading the last position, so plrStep() signals EOF by setting + ** pData to NULL. + */ + const char *pData; + int nData; + + DocListType iType; + int iColumn; /* the last column read */ + int iPosition; /* the last position read */ + int iStartOffset; /* the last start offset read */ + int iEndOffset; /* the last end offset read */ +} PLReader; + +static int plrAtEnd(PLReader *pReader){ + return pReader->pData==NULL; +} +static int plrColumn(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iColumn; +} +static int plrPosition(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iPosition; +} +static int plrStartOffset(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iStartOffset; +} +static int plrEndOffset(PLReader *pReader){ + assert( !plrAtEnd(pReader) ); + return pReader->iEndOffset; +} +static void plrStep(PLReader *pReader){ + int i, n; + + assert( !plrAtEnd(pReader) ); + + if( pReader->nData==0 ){ + pReader->pData = NULL; + return; + } + + n = fts3GetVarint32(pReader->pData, &i); + if( i==POS_COLUMN ){ + n += fts3GetVarint32(pReader->pData+n, &pReader->iColumn); + pReader->iPosition = 0; + pReader->iStartOffset = 0; + n += fts3GetVarint32(pReader->pData+n, &i); + } + /* Should never see adjacent column changes. */ + assert( i!=POS_COLUMN ); + + if( i==POS_END ){ + pReader->nData = 0; + pReader->pData = NULL; + return; + } + + pReader->iPosition += i-POS_BASE; + if( pReader->iType==DL_POSITIONS_OFFSETS ){ + n += fts3GetVarint32(pReader->pData+n, &i); + pReader->iStartOffset += i; + n += fts3GetVarint32(pReader->pData+n, &i); + pReader->iEndOffset = pReader->iStartOffset+i; + } + assert( n<=pReader->nData ); + pReader->pData += n; + pReader->nData -= n; +} + +static void plrInit(PLReader *pReader, DLReader *pDLReader){ + pReader->pData = dlrPosData(pDLReader); + pReader->nData = dlrPosDataLen(pDLReader); + pReader->iType = pDLReader->iType; + pReader->iColumn = 0; + pReader->iPosition = 0; + pReader->iStartOffset = 0; + pReader->iEndOffset = 0; + plrStep(pReader); +} +static void plrDestroy(PLReader *pReader){ + SCRAMBLE(pReader); +} + +/*******************************************************************/ +/* PLWriter is used in constructing a document's position list. As a +** convenience, if iType is DL_DOCIDS, PLWriter becomes a no-op. +** PLWriter writes to the associated DLWriter's buffer. +** +** plwInit - init for writing a document's poslist. +** plwDestroy - clear a writer. +** plwAdd - append position and offset information. +** plwCopy - copy next position's data from reader to writer. +** plwTerminate - add any necessary doclist terminator. +** +** Calling plwAdd() after plwTerminate() may result in a corrupt +** doclist. +*/ +/* TODO(shess) Until we've written the second item, we can cache the +** first item's information. Then we'd have three states: +** +** - initialized with docid, no positions. +** - docid and one position. +** - docid and multiple positions. +** +** Only the last state needs to actually write to dlw->b, which would +** be an improvement in the DLCollector case. +*/ +typedef struct PLWriter { + DLWriter *dlw; + + int iColumn; /* the last column written */ + int iPos; /* the last position written */ + int iOffset; /* the last start offset written */ +} PLWriter; + +/* TODO(shess) In the case where the parent is reading these values +** from a PLReader, we could optimize to a copy if that PLReader has +** the same type as pWriter. +*/ +static void plwAdd(PLWriter *pWriter, int iColumn, int iPos, + int iStartOffset, int iEndOffset){ + /* Worst-case space for POS_COLUMN, iColumn, iPosDelta, + ** iStartOffsetDelta, and iEndOffsetDelta. + */ + char c[5*VARINT_MAX]; + int n = 0; + + /* Ban plwAdd() after plwTerminate(). */ + assert( pWriter->iPos!=-1 ); + + if( pWriter->dlw->iType==DL_DOCIDS ) return; + + if( iColumn!=pWriter->iColumn ){ + n += fts3PutVarint(c+n, POS_COLUMN); + n += fts3PutVarint(c+n, iColumn); + pWriter->iColumn = iColumn; + pWriter->iPos = 0; + pWriter->iOffset = 0; + } + assert( iPos>=pWriter->iPos ); + n += fts3PutVarint(c+n, POS_BASE+(iPos-pWriter->iPos)); + pWriter->iPos = iPos; + if( pWriter->dlw->iType==DL_POSITIONS_OFFSETS ){ + assert( iStartOffset>=pWriter->iOffset ); + n += fts3PutVarint(c+n, iStartOffset-pWriter->iOffset); + pWriter->iOffset = iStartOffset; + assert( iEndOffset>=iStartOffset ); + n += fts3PutVarint(c+n, iEndOffset-iStartOffset); + } + dataBufferAppend(pWriter->dlw->b, c, n); +} +static void plwCopy(PLWriter *pWriter, PLReader *pReader){ + plwAdd(pWriter, plrColumn(pReader), plrPosition(pReader), + plrStartOffset(pReader), plrEndOffset(pReader)); +} +static void plwInit(PLWriter *pWriter, DLWriter *dlw, sqlite_int64 iDocid){ + char c[VARINT_MAX]; + int n; + + pWriter->dlw = dlw; + + /* Docids must ascend. */ + assert( !pWriter->dlw->has_iPrevDocid || iDocid>pWriter->dlw->iPrevDocid ); + n = fts3PutVarint(c, iDocid-pWriter->dlw->iPrevDocid); + dataBufferAppend(pWriter->dlw->b, c, n); + pWriter->dlw->iPrevDocid = iDocid; +#ifndef NDEBUG + pWriter->dlw->has_iPrevDocid = 1; +#endif + + pWriter->iColumn = 0; + pWriter->iPos = 0; + pWriter->iOffset = 0; +} +/* TODO(shess) Should plwDestroy() also terminate the doclist? But +** then plwDestroy() would no longer be just a destructor, it would +** also be doing work, which isn't consistent with the overall idiom. +** Another option would be for plwAdd() to always append any necessary +** terminator, so that the output is always correct. But that would +** add incremental work to the common case with the only benefit being +** API elegance. Punt for now. +*/ +static void plwTerminate(PLWriter *pWriter){ + if( pWriter->dlw->iType>DL_DOCIDS ){ + char c[VARINT_MAX]; + int n = fts3PutVarint(c, POS_END); + dataBufferAppend(pWriter->dlw->b, c, n); + } +#ifndef NDEBUG + /* Mark as terminated for assert in plwAdd(). */ + pWriter->iPos = -1; +#endif +} +static void plwDestroy(PLWriter *pWriter){ + SCRAMBLE(pWriter); +} + +/*******************************************************************/ +/* DLCollector wraps PLWriter and DLWriter to provide a +** dynamically-allocated doclist area to use during tokenization. +** +** dlcNew - malloc up and initialize a collector. +** dlcDelete - destroy a collector and all contained items. +** dlcAddPos - append position and offset information. +** dlcAddDoclist - add the collected doclist to the given buffer. +** dlcNext - terminate the current document and open another. +*/ +typedef struct DLCollector { + DataBuffer b; + DLWriter dlw; + PLWriter plw; +} DLCollector; + +/* TODO(shess) This could also be done by calling plwTerminate() and +** dataBufferAppend(). I tried that, expecting nominal performance +** differences, but it seemed to pretty reliably be worth 1% to code +** it this way. I suspect it is the incremental malloc overhead (some +** percentage of the plwTerminate() calls will cause a realloc), so +** this might be worth revisiting if the DataBuffer implementation +** changes. +*/ +static void dlcAddDoclist(DLCollector *pCollector, DataBuffer *b){ + if( pCollector->dlw.iType>DL_DOCIDS ){ + char c[VARINT_MAX]; + int n = fts3PutVarint(c, POS_END); + dataBufferAppend2(b, pCollector->b.pData, pCollector->b.nData, c, n); + }else{ + dataBufferAppend(b, pCollector->b.pData, pCollector->b.nData); + } +} +static void dlcNext(DLCollector *pCollector, sqlite_int64 iDocid){ + plwTerminate(&pCollector->plw); + plwDestroy(&pCollector->plw); + plwInit(&pCollector->plw, &pCollector->dlw, iDocid); +} +static void dlcAddPos(DLCollector *pCollector, int iColumn, int iPos, + int iStartOffset, int iEndOffset){ + plwAdd(&pCollector->plw, iColumn, iPos, iStartOffset, iEndOffset); +} + +static DLCollector *dlcNew(sqlite_int64 iDocid, DocListType iType){ + DLCollector *pCollector = sqlite3_malloc(sizeof(DLCollector)); + dataBufferInit(&pCollector->b, 0); + dlwInit(&pCollector->dlw, iType, &pCollector->b); + plwInit(&pCollector->plw, &pCollector->dlw, iDocid); + return pCollector; +} +static void dlcDelete(DLCollector *pCollector){ + plwDestroy(&pCollector->plw); + dlwDestroy(&pCollector->dlw); + dataBufferDestroy(&pCollector->b); + SCRAMBLE(pCollector); + sqlite3_free(pCollector); +} + + +/* Copy the doclist data of iType in pData/nData into *out, trimming +** unnecessary data as we go. Only columns matching iColumn are +** copied, all columns copied if iColumn is -1. Elements with no +** matching columns are dropped. The output is an iOutType doclist. +*/ +/* NOTE(shess) This code is only valid after all doclists are merged. +** If this is run before merges, then doclist items which represent +** deletion will be trimmed, and will thus not effect a deletion +** during the merge. +*/ +static void docListTrim(DocListType iType, const char *pData, int nData, + int iColumn, DocListType iOutType, DataBuffer *out){ + DLReader dlReader; + DLWriter dlWriter; + + assert( iOutType<=iType ); + + dlrInit(&dlReader, iType, pData, nData); + dlwInit(&dlWriter, iOutType, out); + + while( !dlrAtEnd(&dlReader) ){ + PLReader plReader; + PLWriter plWriter; + int match = 0; + + plrInit(&plReader, &dlReader); + + while( !plrAtEnd(&plReader) ){ + if( iColumn==-1 || plrColumn(&plReader)==iColumn ){ + if( !match ){ + plwInit(&plWriter, &dlWriter, dlrDocid(&dlReader)); + match = 1; + } + plwAdd(&plWriter, plrColumn(&plReader), plrPosition(&plReader), + plrStartOffset(&plReader), plrEndOffset(&plReader)); + } + plrStep(&plReader); + } + if( match ){ + plwTerminate(&plWriter); + plwDestroy(&plWriter); + } + + plrDestroy(&plReader); + dlrStep(&dlReader); + } + dlwDestroy(&dlWriter); + dlrDestroy(&dlReader); +} + +/* Used by docListMerge() to keep doclists in the ascending order by +** docid, then ascending order by age (so the newest comes first). +*/ +typedef struct OrderedDLReader { + DLReader *pReader; + + /* TODO(shess) If we assume that docListMerge pReaders is ordered by + ** age (which we do), then we could use pReader comparisons to break + ** ties. + */ + int idx; +} OrderedDLReader; + +/* Order eof to end, then by docid asc, idx desc. */ +static int orderedDLReaderCmp(OrderedDLReader *r1, OrderedDLReader *r2){ + if( dlrAtEnd(r1->pReader) ){ + if( dlrAtEnd(r2->pReader) ) return 0; /* Both atEnd(). */ + return 1; /* Only r1 atEnd(). */ + } + if( dlrAtEnd(r2->pReader) ) return -1; /* Only r2 atEnd(). */ + + if( dlrDocid(r1->pReader)pReader) ) return -1; + if( dlrDocid(r1->pReader)>dlrDocid(r2->pReader) ) return 1; + + /* Descending on idx. */ + return r2->idx-r1->idx; +} + +/* Bubble p[0] to appropriate place in p[1..n-1]. Assumes that +** p[1..n-1] is already sorted. +*/ +/* TODO(shess) Is this frequent enough to warrant a binary search? +** Before implementing that, instrument the code to check. In most +** current usage, I expect that p[0] will be less than p[1] a very +** high proportion of the time. +*/ +static void orderedDLReaderReorder(OrderedDLReader *p, int n){ + while( n>1 && orderedDLReaderCmp(p, p+1)>0 ){ + OrderedDLReader tmp = p[0]; + p[0] = p[1]; + p[1] = tmp; + n--; + p++; + } +} + +/* Given an array of doclist readers, merge their doclist elements +** into out in sorted order (by docid), dropping elements from older +** readers when there is a duplicate docid. pReaders is assumed to be +** ordered by age, oldest first. +*/ +/* TODO(shess) nReaders must be <= MERGE_COUNT. This should probably +** be fixed. +*/ +static void docListMerge(DataBuffer *out, + DLReader *pReaders, int nReaders){ + OrderedDLReader readers[MERGE_COUNT]; + DLWriter writer; + int i, n; + const char *pStart = 0; + int nStart = 0; + sqlite_int64 iFirstDocid = 0, iLastDocid = 0; + + assert( nReaders>0 ); + if( nReaders==1 ){ + dataBufferAppend(out, dlrDocData(pReaders), dlrAllDataBytes(pReaders)); + return; + } + + assert( nReaders<=MERGE_COUNT ); + n = 0; + for(i=0; i0 ){ + orderedDLReaderReorder(readers+i, nReaders-i); + } + + dlwInit(&writer, pReaders[0].iType, out); + while( !dlrAtEnd(readers[0].pReader) ){ + sqlite_int64 iDocid = dlrDocid(readers[0].pReader); + + /* If this is a continuation of the current buffer to copy, extend + ** that buffer. memcpy() seems to be more efficient if it has a + ** lots of data to copy. + */ + if( dlrDocData(readers[0].pReader)==pStart+nStart ){ + nStart += dlrDocDataBytes(readers[0].pReader); + }else{ + if( pStart!=0 ){ + dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); + } + pStart = dlrDocData(readers[0].pReader); + nStart = dlrDocDataBytes(readers[0].pReader); + iFirstDocid = iDocid; + } + iLastDocid = iDocid; + dlrStep(readers[0].pReader); + + /* Drop all of the older elements with the same docid. */ + for(i=1; i0 ){ + orderedDLReaderReorder(readers+i, nReaders-i); + } + } + + /* Copy over any remaining elements. */ + if( nStart>0 ) dlwAppend(&writer, pStart, nStart, iFirstDocid, iLastDocid); + dlwDestroy(&writer); +} + +/* Helper function for posListUnion(). Compares the current position +** between left and right, returning as standard C idiom of <0 if +** left0 if left>right, and 0 if left==right. "End" always +** compares greater. +*/ +static int posListCmp(PLReader *pLeft, PLReader *pRight){ + assert( pLeft->iType==pRight->iType ); + if( pLeft->iType==DL_DOCIDS ) return 0; + + if( plrAtEnd(pLeft) ) return plrAtEnd(pRight) ? 0 : 1; + if( plrAtEnd(pRight) ) return -1; + + if( plrColumn(pLeft)plrColumn(pRight) ) return 1; + + if( plrPosition(pLeft)plrPosition(pRight) ) return 1; + if( pLeft->iType==DL_POSITIONS ) return 0; + + if( plrStartOffset(pLeft)plrStartOffset(pRight) ) return 1; + + if( plrEndOffset(pLeft)plrEndOffset(pRight) ) return 1; + + return 0; +} + +/* Write the union of position lists in pLeft and pRight to pOut. +** "Union" in this case meaning "All unique position tuples". Should +** work with any doclist type, though both inputs and the output +** should be the same type. +*/ +static void posListUnion(DLReader *pLeft, DLReader *pRight, DLWriter *pOut){ + PLReader left, right; + PLWriter writer; + + assert( dlrDocid(pLeft)==dlrDocid(pRight) ); + assert( pLeft->iType==pRight->iType ); + assert( pLeft->iType==pOut->iType ); + + plrInit(&left, pLeft); + plrInit(&right, pRight); + plwInit(&writer, pOut, dlrDocid(pLeft)); + + while( !plrAtEnd(&left) || !plrAtEnd(&right) ){ + int c = posListCmp(&left, &right); + if( c<0 ){ + plwCopy(&writer, &left); + plrStep(&left); + }else if( c>0 ){ + plwCopy(&writer, &right); + plrStep(&right); + }else{ + plwCopy(&writer, &left); + plrStep(&left); + plrStep(&right); + } + } + + plwTerminate(&writer); + plwDestroy(&writer); + plrDestroy(&left); + plrDestroy(&right); +} + +/* Write the union of doclists in pLeft and pRight to pOut. For +** docids in common between the inputs, the union of the position +** lists is written. Inputs and outputs are always type DL_DEFAULT. +*/ +static void docListUnion( + const char *pLeft, int nLeft, + const char *pRight, int nRight, + DataBuffer *pOut /* Write the combined doclist here */ +){ + DLReader left, right; + DLWriter writer; + + if( nLeft==0 ){ + if( nRight!=0) dataBufferAppend(pOut, pRight, nRight); + return; + } + if( nRight==0 ){ + dataBufferAppend(pOut, pLeft, nLeft); + return; + } + + dlrInit(&left, DL_DEFAULT, pLeft, nLeft); + dlrInit(&right, DL_DEFAULT, pRight, nRight); + dlwInit(&writer, DL_DEFAULT, pOut); + + while( !dlrAtEnd(&left) || !dlrAtEnd(&right) ){ + if( dlrAtEnd(&right) ){ + dlwCopy(&writer, &left); + dlrStep(&left); + }else if( dlrAtEnd(&left) ){ + dlwCopy(&writer, &right); + dlrStep(&right); + }else if( dlrDocid(&left)dlrDocid(&right) ){ + dlwCopy(&writer, &right); + dlrStep(&right); + }else{ + posListUnion(&left, &right, &writer); + dlrStep(&left); + dlrStep(&right); + } + } + + dlrDestroy(&left); + dlrDestroy(&right); + dlwDestroy(&writer); +} + +/* +** This function is used as part of the implementation of phrase and +** NEAR matching. +** +** pLeft and pRight are DLReaders positioned to the same docid in +** lists of type DL_POSITION. This function writes an entry to the +** DLWriter pOut for each position in pRight that is less than +** (nNear+1) greater (but not equal to or smaller) than a position +** in pLeft. For example, if nNear is 0, and the positions contained +** by pLeft and pRight are: +** +** pLeft: 5 10 15 20 +** pRight: 6 9 17 21 +** +** then the docid is added to pOut. If pOut is of type DL_POSITIONS, +** then a positionids "6" and "21" are also added to pOut. +** +** If boolean argument isSaveLeft is true, then positionids are copied +** from pLeft instead of pRight. In the example above, the positions "5" +** and "20" would be added instead of "6" and "21". +*/ +static void posListPhraseMerge( + DLReader *pLeft, + DLReader *pRight, + int nNear, + int isSaveLeft, + DLWriter *pOut +){ + PLReader left, right; + PLWriter writer; + int match = 0; + + assert( dlrDocid(pLeft)==dlrDocid(pRight) ); + assert( pOut->iType!=DL_POSITIONS_OFFSETS ); + + plrInit(&left, pLeft); + plrInit(&right, pRight); + + while( !plrAtEnd(&left) && !plrAtEnd(&right) ){ + if( plrColumn(&left)plrColumn(&right) ){ + plrStep(&right); + }else if( plrPosition(&left)>=plrPosition(&right) ){ + plrStep(&right); + }else{ + if( (plrPosition(&right)-plrPosition(&left))<=(nNear+1) ){ + if( !match ){ + plwInit(&writer, pOut, dlrDocid(pLeft)); + match = 1; + } + if( !isSaveLeft ){ + plwAdd(&writer, plrColumn(&right), plrPosition(&right), 0, 0); + }else{ + plwAdd(&writer, plrColumn(&left), plrPosition(&left), 0, 0); + } + plrStep(&right); + }else{ + plrStep(&left); + } + } + } + + if( match ){ + plwTerminate(&writer); + plwDestroy(&writer); + } + + plrDestroy(&left); + plrDestroy(&right); +} + +/* +** Compare the values pointed to by the PLReaders passed as arguments. +** Return -1 if the value pointed to by pLeft is considered less than +** the value pointed to by pRight, +1 if it is considered greater +** than it, or 0 if it is equal. i.e. +** +** (*pLeft - *pRight) +** +** A PLReader that is in the EOF condition is considered greater than +** any other. If neither argument is in EOF state, the return value of +** plrColumn() is used. If the plrColumn() values are equal, the +** comparison is on the basis of plrPosition(). +*/ +static int plrCompare(PLReader *pLeft, PLReader *pRight){ + assert(!plrAtEnd(pLeft) || !plrAtEnd(pRight)); + + if( plrAtEnd(pRight) || plrAtEnd(pLeft) ){ + return (plrAtEnd(pRight) ? -1 : 1); + } + if( plrColumn(pLeft)!=plrColumn(pRight) ){ + return ((plrColumn(pLeft)0) +** and write the results into pOut. +** +** A phrase intersection means that two documents only match +** if pLeft.iPos+1==pRight.iPos. +** +** A NEAR intersection means that two documents only match if +** (abs(pLeft.iPos-pRight.iPos) one AND (two OR three) + * [one OR two three] ==> (one OR two) AND three + * + * A "-" before a term matches all entries that lack that term. + * The "-" must occur immediately before the term with in intervening + * space. This is how the search engines do it. + * + * A NOT term cannot be the right-hand operand of an OR. If this + * occurs in the query string, the NOT is ignored: + * + * [one OR -two] ==> one OR two + * + */ +typedef struct Query { + fulltext_vtab *pFts; /* The full text index */ + int nTerms; /* Number of terms in the query */ + QueryTerm *pTerms; /* Array of terms. Space obtained from malloc() */ + int nextIsOr; /* Set the isOr flag on the next inserted term */ + int nextIsNear; /* Set the isOr flag on the next inserted term */ + int nextColumn; /* Next word parsed must be in this column */ + int dfltColumn; /* The default column */ +} Query; + + +/* +** An instance of the following structure keeps track of generated +** matching-word offset information and snippets. +*/ +typedef struct Snippet { + int nMatch; /* Total number of matches */ + int nAlloc; /* Space allocated for aMatch[] */ + struct snippetMatch { /* One entry for each matching term */ + char snStatus; /* Status flag for use while constructing snippets */ + short int iCol; /* The column that contains the match */ + short int iTerm; /* The index in Query.pTerms[] of the matching term */ + int iToken; /* The index of the matching document token */ + short int nByte; /* Number of bytes in the term */ + int iStart; /* The offset to the first character of the term */ + } *aMatch; /* Points to space obtained from malloc */ + char *zOffset; /* Text rendering of aMatch[] */ + int nOffset; /* strlen(zOffset) */ + char *zSnippet; /* Snippet text */ + int nSnippet; /* strlen(zSnippet) */ +} Snippet; + + +typedef enum QueryType { + QUERY_GENERIC, /* table scan */ + QUERY_DOCID, /* lookup by docid */ + QUERY_FULLTEXT /* QUERY_FULLTEXT + [i] is a full-text search for column i*/ +} QueryType; + +typedef enum fulltext_statement { + CONTENT_INSERT_STMT, + CONTENT_SELECT_STMT, + CONTENT_UPDATE_STMT, + CONTENT_DELETE_STMT, + + BLOCK_INSERT_STMT, + BLOCK_SELECT_STMT, + BLOCK_DELETE_STMT, + + SEGDIR_MAX_INDEX_STMT, + SEGDIR_SET_STMT, + SEGDIR_SELECT_STMT, + SEGDIR_SPAN_STMT, + SEGDIR_DELETE_STMT, + SEGDIR_SELECT_ALL_STMT, + + MAX_STMT /* Always at end! */ +} fulltext_statement; + +/* These must exactly match the enum above. */ +/* TODO(shess): Is there some risk that a statement will be used in two +** cursors at once, e.g. if a query joins a virtual table to itself? +** If so perhaps we should move some of these to the cursor object. +*/ +static const char *const fulltext_zStatement[MAX_STMT] = { + /* CONTENT_INSERT */ NULL, /* generated in contentInsertStatement() */ + /* CONTENT_SELECT */ NULL, /* generated in contentSelectStatement() */ + /* CONTENT_UPDATE */ NULL, /* generated in contentUpdateStatement() */ + /* CONTENT_DELETE */ "delete from %_content where docid = ?", + + /* BLOCK_INSERT */ + "insert into %_segments (blockid, block) values (null, ?)", + /* BLOCK_SELECT */ "select block from %_segments where blockid = ?", + /* BLOCK_DELETE */ "delete from %_segments where blockid between ? and ?", + + /* SEGDIR_MAX_INDEX */ "select max(idx) from %_segdir where level = ?", + /* SEGDIR_SET */ "insert into %_segdir values (?, ?, ?, ?, ?, ?)", + /* SEGDIR_SELECT */ + "select start_block, leaves_end_block, root from %_segdir " + " where level = ? order by idx", + /* SEGDIR_SPAN */ + "select min(start_block), max(end_block) from %_segdir " + " where level = ? and start_block <> 0", + /* SEGDIR_DELETE */ "delete from %_segdir where level = ?", + /* SEGDIR_SELECT_ALL */ + "select root, leaves_end_block from %_segdir order by level desc, idx", +}; + +/* +** A connection to a fulltext index is an instance of the following +** structure. The xCreate and xConnect methods create an instance +** of this structure and xDestroy and xDisconnect free that instance. +** All other methods receive a pointer to the structure as one of their +** arguments. +*/ +struct fulltext_vtab { + sqlite3_vtab base; /* Base class used by SQLite core */ + sqlite3 *db; /* The database connection */ + const char *zDb; /* logical database name */ + const char *zName; /* virtual table name */ + int nColumn; /* number of columns in virtual table */ + char **azColumn; /* column names. malloced */ + char **azContentColumn; /* column names in content table; malloced */ + sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ + + /* Precompiled statements which we keep as long as the table is + ** open. + */ + sqlite3_stmt *pFulltextStatements[MAX_STMT]; + + /* Precompiled statements used for segment merges. We run a + ** separate select across the leaf level of each tree being merged. + */ + sqlite3_stmt *pLeafSelectStmts[MERGE_COUNT]; + /* The statement used to prepare pLeafSelectStmts. */ +#define LEAF_SELECT \ + "select block from %_segments where blockid between ? and ? order by blockid" + + /* These buffer pending index updates during transactions. + ** nPendingData estimates the memory size of the pending data. It + ** doesn't include the hash-bucket overhead, nor any malloc + ** overhead. When nPendingData exceeds kPendingThreshold, the + ** buffer is flushed even before the transaction closes. + ** pendingTerms stores the data, and is only valid when nPendingData + ** is >=0 (nPendingData<0 means pendingTerms has not been + ** initialized). iPrevDocid is the last docid written, used to make + ** certain we're inserting in sorted order. + */ + int nPendingData; +#define kPendingThreshold (1*1024*1024) + sqlite_int64 iPrevDocid; + fts3Hash pendingTerms; +}; + +/* +** When the core wants to do a query, it create a cursor using a +** call to xOpen. This structure is an instance of a cursor. It +** is destroyed by xClose. +*/ +typedef struct fulltext_cursor { + sqlite3_vtab_cursor base; /* Base class used by SQLite core */ + QueryType iCursorType; /* Copy of sqlite3_index_info.idxNum */ + sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ + int eof; /* True if at End Of Results */ + Query q; /* Parsed query string */ + Snippet snippet; /* Cached snippet for the current row */ + int iColumn; /* Column being searched */ + DataBuffer result; /* Doclist results from fulltextQuery */ + DLReader reader; /* Result reader if result not empty */ +} fulltext_cursor; + +static struct fulltext_vtab *cursor_vtab(fulltext_cursor *c){ + return (fulltext_vtab *) c->base.pVtab; +} + +static const sqlite3_module fts3Module; /* forward declaration */ + +/* Return a dynamically generated statement of the form + * insert into %_content (docid, ...) values (?, ...) + */ +static const char *contentInsertStatement(fulltext_vtab *v){ + StringBuffer sb; + int i; + + initStringBuffer(&sb); + append(&sb, "insert into %_content (docid, "); + appendList(&sb, v->nColumn, v->azContentColumn); + append(&sb, ") values (?"); + for(i=0; inColumn; ++i) + append(&sb, ", ?"); + append(&sb, ")"); + return stringBufferData(&sb); +} + +/* Return a dynamically generated statement of the form + * select from %_content where docid = ? + */ +static const char *contentSelectStatement(fulltext_vtab *v){ + StringBuffer sb; + initStringBuffer(&sb); + append(&sb, "SELECT "); + appendList(&sb, v->nColumn, v->azContentColumn); + append(&sb, " FROM %_content WHERE docid = ?"); + return stringBufferData(&sb); +} + +/* Return a dynamically generated statement of the form + * update %_content set [col_0] = ?, [col_1] = ?, ... + * where docid = ? + */ +static const char *contentUpdateStatement(fulltext_vtab *v){ + StringBuffer sb; + int i; + + initStringBuffer(&sb); + append(&sb, "update %_content set "); + for(i=0; inColumn; ++i) { + if( i>0 ){ + append(&sb, ", "); + } + append(&sb, v->azContentColumn[i]); + append(&sb, " = ?"); + } + append(&sb, " where docid = ?"); + return stringBufferData(&sb); +} + +/* Puts a freshly-prepared statement determined by iStmt in *ppStmt. +** If the indicated statement has never been prepared, it is prepared +** and cached, otherwise the cached version is reset. +*/ +static int sql_get_statement(fulltext_vtab *v, fulltext_statement iStmt, + sqlite3_stmt **ppStmt){ + assert( iStmtpFulltextStatements[iStmt]==NULL ){ + const char *zStmt; + int rc; + switch( iStmt ){ + case CONTENT_INSERT_STMT: + zStmt = contentInsertStatement(v); break; + case CONTENT_SELECT_STMT: + zStmt = contentSelectStatement(v); break; + case CONTENT_UPDATE_STMT: + zStmt = contentUpdateStatement(v); break; + default: + zStmt = fulltext_zStatement[iStmt]; + } + rc = sql_prepare(v->db, v->zDb, v->zName, &v->pFulltextStatements[iStmt], + zStmt); + if( zStmt != fulltext_zStatement[iStmt]) sqlite3_free((void *) zStmt); + if( rc!=SQLITE_OK ) return rc; + } else { + int rc = sqlite3_reset(v->pFulltextStatements[iStmt]); + if( rc!=SQLITE_OK ) return rc; + } + + *ppStmt = v->pFulltextStatements[iStmt]; + return SQLITE_OK; +} + +/* Like sqlite3_step(), but convert SQLITE_DONE to SQLITE_OK and +** SQLITE_ROW to SQLITE_ERROR. Useful for statements like UPDATE, +** where we expect no results. +*/ +static int sql_single_step(sqlite3_stmt *s){ + int rc = sqlite3_step(s); + return (rc==SQLITE_DONE) ? SQLITE_OK : rc; +} + +/* Like sql_get_statement(), but for special replicated LEAF_SELECT +** statements. +*/ +/* TODO(shess) Write version for generic statements and then share +** that between the cached-statement functions. +*/ +static int sql_get_leaf_statement(fulltext_vtab *v, int idx, + sqlite3_stmt **ppStmt){ + assert( idx>=0 && idxpLeafSelectStmts[idx]==NULL ){ + int rc = sql_prepare(v->db, v->zDb, v->zName, &v->pLeafSelectStmts[idx], + LEAF_SELECT); + if( rc!=SQLITE_OK ) return rc; + }else{ + int rc = sqlite3_reset(v->pLeafSelectStmts[idx]); + if( rc!=SQLITE_OK ) return rc; + } + + *ppStmt = v->pLeafSelectStmts[idx]; + return SQLITE_OK; +} + +/* insert into %_content (docid, ...) values ([docid], [pValues]) +** If the docid contains SQL NULL, then a unique docid will be +** generated. +*/ +static int content_insert(fulltext_vtab *v, sqlite3_value *docid, + sqlite3_value **pValues){ + sqlite3_stmt *s; + int i; + int rc = sql_get_statement(v, CONTENT_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_value(s, 1, docid); + if( rc!=SQLITE_OK ) return rc; + + for(i=0; inColumn; ++i){ + rc = sqlite3_bind_value(s, 2+i, pValues[i]); + if( rc!=SQLITE_OK ) return rc; + } + + return sql_single_step(s); +} + +/* update %_content set col0 = pValues[0], col1 = pValues[1], ... + * where docid = [iDocid] */ +static int content_update(fulltext_vtab *v, sqlite3_value **pValues, + sqlite_int64 iDocid){ + sqlite3_stmt *s; + int i; + int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + for(i=0; inColumn; ++i){ + rc = sqlite3_bind_value(s, 1+i, pValues[i]); + if( rc!=SQLITE_OK ) return rc; + } + + rc = sqlite3_bind_int64(s, 1+v->nColumn, iDocid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +static void freeStringArray(int nString, const char **pString){ + int i; + + for (i=0 ; i < nString ; ++i) { + if( pString[i]!=NULL ) sqlite3_free((void *) pString[i]); + } + sqlite3_free((void *) pString); +} + +/* select * from %_content where docid = [iDocid] + * The caller must delete the returned array and all strings in it. + * null fields will be NULL in the returned array. + * + * TODO: Perhaps we should return pointer/length strings here for consistency + * with other code which uses pointer/length. */ +static int content_select(fulltext_vtab *v, sqlite_int64 iDocid, + const char ***pValues){ + sqlite3_stmt *s; + const char **values; + int i; + int rc; + + *pValues = NULL; + + rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iDocid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc!=SQLITE_ROW ) return rc; + + values = (const char **) sqlite3_malloc(v->nColumn * sizeof(const char *)); + for(i=0; inColumn; ++i){ + if( sqlite3_column_type(s, i)==SQLITE_NULL ){ + values[i] = NULL; + }else{ + values[i] = string_dup((char*)sqlite3_column_text(s, i)); + } + } + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ){ + *pValues = values; + return SQLITE_OK; + } + + freeStringArray(v->nColumn, values); + return rc; +} + +/* delete from %_content where docid = [iDocid ] */ +static int content_delete(fulltext_vtab *v, sqlite_int64 iDocid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iDocid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* insert into %_segments values ([pData]) +** returns assigned blockid in *piBlockid +*/ +static int block_insert(fulltext_vtab *v, const char *pData, int nData, + sqlite_int64 *piBlockid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + + /* blockid column is an alias for rowid. */ + *piBlockid = sqlite3_last_insert_rowid(v->db); + return SQLITE_OK; +} + +/* delete from %_segments +** where blockid between [iStartBlockid] and [iEndBlockid] +** +** Deletes the range of blocks, inclusive, used to delete the blocks +** which form a segment. +*/ +static int block_delete(fulltext_vtab *v, + sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iStartBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found +** at iLevel. Returns SQLITE_DONE if there are no segments at +** iLevel. Otherwise returns an error. +*/ +static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + /* Should always get at least one row due to how max() works. */ + if( rc==SQLITE_DONE ) return SQLITE_DONE; + if( rc!=SQLITE_ROW ) return rc; + + /* NULL means that there were no inputs to max(). */ + if( SQLITE_NULL==sqlite3_column_type(s, 0) ){ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + return rc; + } + + *pidx = sqlite3_column_int(s, 0); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + return SQLITE_ROW; +} + +/* insert into %_segdir values ( +** [iLevel], [idx], +** [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid], +** [pRootData] +** ) +*/ +static int segdir_set(fulltext_vtab *v, int iLevel, int idx, + sqlite_int64 iStartBlockid, + sqlite_int64 iLeavesEndBlockid, + sqlite_int64 iEndBlockid, + const char *pRootData, int nRootData){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 2, idx); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 3, iStartBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 5, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* Queries %_segdir for the block span of the segments in level +** iLevel. Returns SQLITE_DONE if there are no blocks for iLevel, +** SQLITE_ROW if there are blocks, else an error. +*/ +static int segdir_span(fulltext_vtab *v, int iLevel, + sqlite_int64 *piStartBlockid, + sqlite_int64 *piEndBlockid){ + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ) return SQLITE_DONE; /* Should never happen */ + if( rc!=SQLITE_ROW ) return rc; + + /* This happens if all segments at this level are entirely inline. */ + if( SQLITE_NULL==sqlite3_column_type(s, 0) ){ + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + int rc2 = sqlite3_step(s); + if( rc2==SQLITE_ROW ) return SQLITE_ERROR; + return rc2; + } + + *piStartBlockid = sqlite3_column_int64(s, 0); + *piEndBlockid = sqlite3_column_int64(s, 1); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + return SQLITE_ROW; +} + +/* Delete the segment blocks and segment directory records for all +** segments at iLevel. +*/ +static int segdir_delete(fulltext_vtab *v, int iLevel){ + sqlite3_stmt *s; + sqlite_int64 iStartBlockid, iEndBlockid; + int rc = segdir_span(v, iLevel, &iStartBlockid, &iEndBlockid); + if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc; + + if( rc==SQLITE_ROW ){ + rc = block_delete(v, iStartBlockid, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + } + + /* Delete the segment directory itself. */ + rc = sql_get_statement(v, SEGDIR_DELETE_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + return sql_single_step(s); +} + +/* TODO(shess) clearPendingTerms() is far down the file because +** writeZeroSegment() is far down the file because LeafWriter is far +** down the file. Consider refactoring the code to move the non-vtab +** code above the vtab code so that we don't need this forward +** reference. +*/ +static int clearPendingTerms(fulltext_vtab *v); + +/* +** Free the memory used to contain a fulltext_vtab structure. +*/ +static void fulltext_vtab_destroy(fulltext_vtab *v){ + int iStmt, i; + + FTSTRACE(("FTS3 Destroy %p\n", v)); + for( iStmt=0; iStmtpFulltextStatements[iStmt]!=NULL ){ + sqlite3_finalize(v->pFulltextStatements[iStmt]); + v->pFulltextStatements[iStmt] = NULL; + } + } + + for( i=0; ipLeafSelectStmts[i]!=NULL ){ + sqlite3_finalize(v->pLeafSelectStmts[i]); + v->pLeafSelectStmts[i] = NULL; + } + } + + if( v->pTokenizer!=NULL ){ + v->pTokenizer->pModule->xDestroy(v->pTokenizer); + v->pTokenizer = NULL; + } + + clearPendingTerms(v); + + sqlite3_free(v->azColumn); + for(i = 0; i < v->nColumn; ++i) { + sqlite3_free(v->azContentColumn[i]); + } + sqlite3_free(v->azContentColumn); + sqlite3_free(v); +} + +/* +** Token types for parsing the arguments to xConnect or xCreate. +*/ +#define TOKEN_EOF 0 /* End of file */ +#define TOKEN_SPACE 1 /* Any kind of whitespace */ +#define TOKEN_ID 2 /* An identifier */ +#define TOKEN_STRING 3 /* A string literal */ +#define TOKEN_PUNCT 4 /* A single punctuation character */ + +/* +** If X is a character that can be used in an identifier then +** ftsIdChar(X) will be true. Otherwise it is false. +** +** For ASCII, any character with the high-order bit set is +** allowed in an identifier. For 7-bit characters, +** isFtsIdChar[X] must be 1. +** +** Ticket #1066. the SQL standard does not allow '$' in the +** middle of identfiers. But many SQL implementations do. +** SQLite will allow '$' in identifiers for compatibility. +** But the feature is undocumented. +*/ +static const char isFtsIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define ftsIdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && isFtsIdChar[c-0x20])) + + +/* +** Return the length of the token that begins at z[0]. +** Store the token type in *tokenType before returning. +*/ +static int ftsGetToken(const char *z, int *tokenType){ + int i, c; + switch( *z ){ + case 0: { + *tokenType = TOKEN_EOF; + return 0; + } + case ' ': case '\t': case '\n': case '\f': case '\r': { + for(i=1; safe_isspace(z[i]); i++){} + *tokenType = TOKEN_SPACE; + return i; + } + case '`': + case '\'': + case '"': { + int delim = z[0]; + for(i=1; (c=z[i])!=0; i++){ + if( c==delim ){ + if( z[i+1]==delim ){ + i++; + }else{ + break; + } + } + } + *tokenType = TOKEN_STRING; + return i + (c!=0); + } + case '[': { + for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} + *tokenType = TOKEN_ID; + return i; + } + default: { + if( !ftsIdChar(*z) ){ + break; + } + for(i=1; ftsIdChar(z[i]); i++){} + *tokenType = TOKEN_ID; + return i; + } + } + *tokenType = TOKEN_PUNCT; + return 1; +} + +/* +** A token extracted from a string is an instance of the following +** structure. +*/ +typedef struct FtsToken { + const char *z; /* Pointer to token text. Not '\000' terminated */ + short int n; /* Length of the token text in bytes. */ +} FtsToken; + +/* +** Given a input string (which is really one of the argv[] parameters +** passed into xConnect or xCreate) split the string up into tokens. +** Return an array of pointers to '\000' terminated strings, one string +** for each non-whitespace token. +** +** The returned array is terminated by a single NULL pointer. +** +** Space to hold the returned array is obtained from a single +** malloc and should be freed by passing the return value to free(). +** The individual strings within the token list are all a part of +** the single memory allocation and will all be freed at once. +*/ +static char **tokenizeString(const char *z, int *pnToken){ + int nToken = 0; + FtsToken *aToken = sqlite3_malloc( strlen(z) * sizeof(aToken[0]) ); + int n = 1; + int e, i; + int totalSize = 0; + char **azToken; + char *zCopy; + while( n>0 ){ + n = ftsGetToken(z, &e); + if( e!=TOKEN_SPACE ){ + aToken[nToken].z = z; + aToken[nToken].n = n; + nToken++; + totalSize += n+1; + } + z += n; + } + azToken = (char**)sqlite3_malloc( nToken*sizeof(char*) + totalSize ); + zCopy = (char*)&azToken[nToken]; + nToken--; + for(i=0; i=0 ){ + azIn[j] = azIn[i]; + } + j++; + } + } + azIn[j] = 0; + } +} + + +/* +** Find the first alphanumeric token in the string zIn. Null-terminate +** this token. Remove any quotation marks. And return a pointer to +** the result. +*/ +static char *firstToken(char *zIn, char **pzTail){ + int n, ttype; + while(1){ + n = ftsGetToken(zIn, &ttype); + if( ttype==TOKEN_SPACE ){ + zIn += n; + }else if( ttype==TOKEN_EOF ){ + *pzTail = zIn; + return 0; + }else{ + zIn[n] = 0; + *pzTail = &zIn[1]; + dequoteString(zIn); + return zIn; + } + } + /*NOTREACHED*/ +} + +/* Return true if... +** +** * s begins with the string t, ignoring case +** * s is longer than t +** * The first character of s beyond t is not a alphanumeric +** +** Ignore leading space in *s. +** +** To put it another way, return true if the first token of +** s[] is t[]. +*/ +static int startsWith(const char *s, const char *t){ + while( safe_isspace(*s) ){ s++; } + while( *t ){ + if( safe_tolower(*s++)!=safe_tolower(*t++) ) return 0; + } + return *s!='_' && !safe_isalnum(*s); +} + +/* +** An instance of this structure defines the "spec" of a +** full text index. This structure is populated by parseSpec +** and use by fulltextConnect and fulltextCreate. +*/ +typedef struct TableSpec { + const char *zDb; /* Logical database name */ + const char *zName; /* Name of the full-text index */ + int nColumn; /* Number of columns to be indexed */ + char **azColumn; /* Original names of columns to be indexed */ + char **azContentColumn; /* Column names for %_content */ + char **azTokenizer; /* Name of tokenizer and its arguments */ +} TableSpec; + +/* +** Reclaim all of the memory used by a TableSpec +*/ +static void clearTableSpec(TableSpec *p) { + sqlite3_free(p->azColumn); + sqlite3_free(p->azContentColumn); + sqlite3_free(p->azTokenizer); +} + +/* Parse a CREATE VIRTUAL TABLE statement, which looks like this: + * + * CREATE VIRTUAL TABLE email + * USING fts3(subject, body, tokenize mytokenizer(myarg)) + * + * We return parsed information in a TableSpec structure. + * + */ +static int parseSpec(TableSpec *pSpec, int argc, const char *const*argv, + char**pzErr){ + int i, n; + char *z, *zDummy; + char **azArg; + const char *zTokenizer = 0; /* argv[] entry describing the tokenizer */ + + assert( argc>=3 ); + /* Current interface: + ** argv[0] - module name + ** argv[1] - database name + ** argv[2] - table name + ** argv[3..] - columns, optionally followed by tokenizer specification + ** and snippet delimiters specification. + */ + + /* Make a copy of the complete argv[][] array in a single allocation. + ** The argv[][] array is read-only and transient. We can write to the + ** copy in order to modify things and the copy is persistent. + */ + CLEAR(pSpec); + for(i=n=0; izDb = azArg[1]; + pSpec->zName = azArg[2]; + pSpec->nColumn = 0; + pSpec->azColumn = azArg; + zTokenizer = "tokenize simple"; + for(i=3; inColumn] = firstToken(azArg[i], &zDummy); + pSpec->nColumn++; + } + } + if( pSpec->nColumn==0 ){ + azArg[0] = "content"; + pSpec->nColumn = 1; + } + + /* + ** Construct the list of content column names. + ** + ** Each content column name will be of the form cNNAAAA + ** where NN is the column number and AAAA is the sanitized + ** column name. "sanitized" means that special characters are + ** converted to "_". The cNN prefix guarantees that all column + ** names are unique. + ** + ** The AAAA suffix is not strictly necessary. It is included + ** for the convenience of people who might examine the generated + ** %_content table and wonder what the columns are used for. + */ + pSpec->azContentColumn = sqlite3_malloc( pSpec->nColumn * sizeof(char *) ); + if( pSpec->azContentColumn==0 ){ + clearTableSpec(pSpec); + return SQLITE_NOMEM; + } + for(i=0; inColumn; i++){ + char *p; + pSpec->azContentColumn[i] = sqlite3_mprintf("c%d%s", i, azArg[i]); + for (p = pSpec->azContentColumn[i]; *p ; ++p) { + if( !safe_isalnum(*p) ) *p = '_'; + } + } + + /* + ** Parse the tokenizer specification string. + */ + pSpec->azTokenizer = tokenizeString(zTokenizer, &n); + tokenListToIdList(pSpec->azTokenizer); + + return SQLITE_OK; +} + +/* +** Generate a CREATE TABLE statement that describes the schema of +** the virtual table. Return a pointer to this schema string. +** +** Space is obtained from sqlite3_mprintf() and should be freed +** using sqlite3_free(). +*/ +static char *fulltextSchema( + int nColumn, /* Number of columns */ + const char *const* azColumn, /* List of columns */ + const char *zTableName /* Name of the table */ +){ + int i; + char *zSchema, *zNext; + const char *zSep = "("; + zSchema = sqlite3_mprintf("CREATE TABLE x"); + for(i=0; ibase */ + v->db = db; + v->zDb = spec->zDb; /* Freed when azColumn is freed */ + v->zName = spec->zName; /* Freed when azColumn is freed */ + v->nColumn = spec->nColumn; + v->azContentColumn = spec->azContentColumn; + spec->azContentColumn = 0; + v->azColumn = spec->azColumn; + spec->azColumn = 0; + + if( spec->azTokenizer==0 ){ + return SQLITE_NOMEM; + } + + zTok = spec->azTokenizer[0]; + if( !zTok ){ + zTok = "simple"; + } + nTok = strlen(zTok)+1; + + m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zTok, nTok); + if( !m ){ + *pzErr = sqlite3_mprintf("unknown tokenizer: %s", spec->azTokenizer[0]); + rc = SQLITE_ERROR; + goto err; + } + + for(n=0; spec->azTokenizer[n]; n++){} + if( n ){ + rc = m->xCreate(n-1, (const char*const*)&spec->azTokenizer[1], + &v->pTokenizer); + }else{ + rc = m->xCreate(0, 0, &v->pTokenizer); + } + if( rc!=SQLITE_OK ) goto err; + v->pTokenizer->pModule = m; + + /* TODO: verify the existence of backing tables foo_content, foo_term */ + + schema = fulltextSchema(v->nColumn, (const char*const*)v->azColumn, + spec->zName); + rc = sqlite3_declare_vtab(db, schema); + sqlite3_free(schema); + if( rc!=SQLITE_OK ) goto err; + + memset(v->pFulltextStatements, 0, sizeof(v->pFulltextStatements)); + + /* Indicate that the buffer is not live. */ + v->nPendingData = -1; + + *ppVTab = &v->base; + FTSTRACE(("FTS3 Connect %p\n", v)); + + return rc; + +err: + fulltext_vtab_destroy(v); + return rc; +} + +static int fulltextConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, + char **pzErr +){ + TableSpec spec; + int rc = parseSpec(&spec, argc, argv, pzErr); + if( rc!=SQLITE_OK ) return rc; + + rc = constructVtab(db, (fts3Hash *)pAux, &spec, ppVTab, pzErr); + clearTableSpec(&spec); + return rc; +} + +/* The %_content table holds the text of each document, with +** the docid column exposed as the SQLite rowid for the table. +*/ +/* TODO(shess) This comment needs elaboration to match the updated +** code. Work it into the top-of-file comment at that time. +*/ +static int fulltextCreate(sqlite3 *db, void *pAux, + int argc, const char * const *argv, + sqlite3_vtab **ppVTab, char **pzErr){ + int rc; + TableSpec spec; + StringBuffer schema; + FTSTRACE(("FTS3 Create\n")); + + rc = parseSpec(&spec, argc, argv, pzErr); + if( rc!=SQLITE_OK ) return rc; + + initStringBuffer(&schema); + append(&schema, "CREATE TABLE %_content("); + append(&schema, " docid INTEGER PRIMARY KEY,"); + appendList(&schema, spec.nColumn, spec.azContentColumn); + append(&schema, ")"); + rc = sql_exec(db, spec.zDb, spec.zName, stringBufferData(&schema)); + stringBufferDestroy(&schema); + if( rc!=SQLITE_OK ) goto out; + + rc = sql_exec(db, spec.zDb, spec.zName, + "create table %_segments(" + " blockid INTEGER PRIMARY KEY," + " block blob" + ");" + ); + if( rc!=SQLITE_OK ) goto out; + + rc = sql_exec(db, spec.zDb, spec.zName, + "create table %_segdir(" + " level integer," + " idx integer," + " start_block integer," + " leaves_end_block integer," + " end_block integer," + " root blob," + " primary key(level, idx)" + ");"); + if( rc!=SQLITE_OK ) goto out; + + rc = constructVtab(db, (fts3Hash *)pAux, &spec, ppVTab, pzErr); + +out: + clearTableSpec(&spec); + return rc; +} + +/* Decide how to handle an SQL query. */ +static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ + fulltext_vtab *v = (fulltext_vtab *)pVTab; + int i; + FTSTRACE(("FTS3 BestIndex\n")); + + for(i=0; inConstraint; ++i){ + const struct sqlite3_index_constraint *pConstraint; + pConstraint = &pInfo->aConstraint[i]; + if( pConstraint->usable ) { + if( (pConstraint->iColumn==-1 || pConstraint->iColumn==v->nColumn+1) && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + pInfo->idxNum = QUERY_DOCID; /* lookup by docid */ + FTSTRACE(("FTS3 QUERY_DOCID\n")); + } else if( pConstraint->iColumn>=0 && pConstraint->iColumn<=v->nColumn && + pConstraint->op==SQLITE_INDEX_CONSTRAINT_MATCH ){ + /* full-text search */ + pInfo->idxNum = QUERY_FULLTEXT + pConstraint->iColumn; + FTSTRACE(("FTS3 QUERY_FULLTEXT %d\n", pConstraint->iColumn)); + } else continue; + + pInfo->aConstraintUsage[i].argvIndex = 1; + pInfo->aConstraintUsage[i].omit = 1; + + /* An arbitrary value for now. + * TODO: Perhaps docid matches should be considered cheaper than + * full-text searches. */ + pInfo->estimatedCost = 1.0; + + return SQLITE_OK; + } + } + pInfo->idxNum = QUERY_GENERIC; + return SQLITE_OK; +} + +static int fulltextDisconnect(sqlite3_vtab *pVTab){ + FTSTRACE(("FTS3 Disconnect %p\n", pVTab)); + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextDestroy(sqlite3_vtab *pVTab){ + fulltext_vtab *v = (fulltext_vtab *)pVTab; + int rc; + + FTSTRACE(("FTS3 Destroy %p\n", pVTab)); + rc = sql_exec(v->db, v->zDb, v->zName, + "drop table if exists %_content;" + "drop table if exists %_segments;" + "drop table if exists %_segdir;" + ); + if( rc!=SQLITE_OK ) return rc; + + fulltext_vtab_destroy((fulltext_vtab *)pVTab); + return SQLITE_OK; +} + +static int fulltextOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + fulltext_cursor *c; + + c = (fulltext_cursor *) sqlite3_malloc(sizeof(fulltext_cursor)); + if( c ){ + memset(c, 0, sizeof(fulltext_cursor)); + /* sqlite will initialize c->base */ + *ppCursor = &c->base; + FTSTRACE(("FTS3 Open %p: %p\n", pVTab, c)); + return SQLITE_OK; + }else{ + return SQLITE_NOMEM; + } +} + + +/* Free all of the dynamically allocated memory held by *q +*/ +static void queryClear(Query *q){ + int i; + for(i = 0; i < q->nTerms; ++i){ + sqlite3_free(q->pTerms[i].pTerm); + } + sqlite3_free(q->pTerms); + CLEAR(q); +} + +/* Free all of the dynamically allocated memory held by the +** Snippet +*/ +static void snippetClear(Snippet *p){ + sqlite3_free(p->aMatch); + sqlite3_free(p->zOffset); + sqlite3_free(p->zSnippet); + CLEAR(p); +} +/* +** Append a single entry to the p->aMatch[] log. +*/ +static void snippetAppendMatch( + Snippet *p, /* Append the entry to this snippet */ + int iCol, int iTerm, /* The column and query term */ + int iToken, /* Matching token in document */ + int iStart, int nByte /* Offset and size of the match */ +){ + int i; + struct snippetMatch *pMatch; + if( p->nMatch+1>=p->nAlloc ){ + p->nAlloc = p->nAlloc*2 + 10; + p->aMatch = sqlite3_realloc(p->aMatch, p->nAlloc*sizeof(p->aMatch[0]) ); + if( p->aMatch==0 ){ + p->nMatch = 0; + p->nAlloc = 0; + return; + } + } + i = p->nMatch++; + pMatch = &p->aMatch[i]; + pMatch->iCol = iCol; + pMatch->iTerm = iTerm; + pMatch->iToken = iToken; + pMatch->iStart = iStart; + pMatch->nByte = nByte; +} + +/* +** Sizing information for the circular buffer used in snippetOffsetsOfColumn() +*/ +#define FTS3_ROTOR_SZ (32) +#define FTS3_ROTOR_MASK (FTS3_ROTOR_SZ-1) + +/* +** Add entries to pSnippet->aMatch[] for every match that occurs against +** document zDoc[0..nDoc-1] which is stored in column iColumn. +*/ +static void snippetOffsetsOfColumn( + Query *pQuery, + Snippet *pSnippet, + int iColumn, + const char *zDoc, + int nDoc +){ + const sqlite3_tokenizer_module *pTModule; /* The tokenizer module */ + sqlite3_tokenizer *pTokenizer; /* The specific tokenizer */ + sqlite3_tokenizer_cursor *pTCursor; /* Tokenizer cursor */ + fulltext_vtab *pVtab; /* The full text index */ + int nColumn; /* Number of columns in the index */ + const QueryTerm *aTerm; /* Query string terms */ + int nTerm; /* Number of query string terms */ + int i, j; /* Loop counters */ + int rc; /* Return code */ + unsigned int match, prevMatch; /* Phrase search bitmasks */ + const char *zToken; /* Next token from the tokenizer */ + int nToken; /* Size of zToken */ + int iBegin, iEnd, iPos; /* Offsets of beginning and end */ + + /* The following variables keep a circular buffer of the last + ** few tokens */ + unsigned int iRotor = 0; /* Index of current token */ + int iRotorBegin[FTS3_ROTOR_SZ]; /* Beginning offset of token */ + int iRotorLen[FTS3_ROTOR_SZ]; /* Length of token */ + + pVtab = pQuery->pFts; + nColumn = pVtab->nColumn; + pTokenizer = pVtab->pTokenizer; + pTModule = pTokenizer->pModule; + rc = pTModule->xOpen(pTokenizer, zDoc, nDoc, &pTCursor); + if( rc ) return; + pTCursor->pTokenizer = pTokenizer; + aTerm = pQuery->pTerms; + nTerm = pQuery->nTerms; + if( nTerm>=FTS3_ROTOR_SZ ){ + nTerm = FTS3_ROTOR_SZ - 1; + } + prevMatch = 0; + while(1){ + rc = pTModule->xNext(pTCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos); + if( rc ) break; + iRotorBegin[iRotor&FTS3_ROTOR_MASK] = iBegin; + iRotorLen[iRotor&FTS3_ROTOR_MASK] = iEnd-iBegin; + match = 0; + for(i=0; i=0 && iColnToken ) continue; + if( !aTerm[i].isPrefix && aTerm[i].nTerm1 && (prevMatch & (1<=0; j--){ + int k = (iRotor-j) & FTS3_ROTOR_MASK; + snippetAppendMatch(pSnippet, iColumn, i-j, iPos-j, + iRotorBegin[k], iRotorLen[k]); + } + } + } + prevMatch = match<<1; + iRotor++; + } + pTModule->xClose(pTCursor); +} + +/* +** Remove entries from the pSnippet structure to account for the NEAR +** operator. When this is called, pSnippet contains the list of token +** offsets produced by treating all NEAR operators as AND operators. +** This function removes any entries that should not be present after +** accounting for the NEAR restriction. For example, if the queried +** document is: +** +** "A B C D E A" +** +** and the query is: +** +** A NEAR/0 E +** +** then when this function is called the Snippet contains token offsets +** 0, 4 and 5. This function removes the "0" entry (because the first A +** is not near enough to an E). +*/ +static void trimSnippetOffsetsForNear(Query *pQuery, Snippet *pSnippet){ + int ii; + int iDir = 1; + + while(iDir>-2) { + assert( iDir==1 || iDir==-1 ); + for(ii=0; iinMatch; ii++){ + int jj; + int nNear; + struct snippetMatch *pMatch = &pSnippet->aMatch[ii]; + QueryTerm *pQueryTerm = &pQuery->pTerms[pMatch->iTerm]; + + if( (pMatch->iTerm+iDir)<0 + || (pMatch->iTerm+iDir)>=pQuery->nTerms + ){ + continue; + } + + nNear = pQueryTerm->nNear; + if( iDir<0 ){ + nNear = pQueryTerm[-1].nNear; + } + + if( pMatch->iTerm>=0 && nNear ){ + int isOk = 0; + int iNextTerm = pMatch->iTerm+iDir; + int iPrevTerm = iNextTerm; + + int iEndToken; + int iStartToken; + + if( iDir<0 ){ + int nPhrase = 1; + iStartToken = pMatch->iToken; + while( (pMatch->iTerm+nPhrase)nTerms + && pQuery->pTerms[pMatch->iTerm+nPhrase].iPhrase>1 + ){ + nPhrase++; + } + iEndToken = iStartToken + nPhrase - 1; + }else{ + iEndToken = pMatch->iToken; + iStartToken = pMatch->iToken+1-pQueryTerm->iPhrase; + } + + while( pQuery->pTerms[iNextTerm].iPhrase>1 ){ + iNextTerm--; + } + while( (iPrevTerm+1)nTerms && + pQuery->pTerms[iPrevTerm+1].iPhrase>1 + ){ + iPrevTerm++; + } + + for(jj=0; isOk==0 && jjnMatch; jj++){ + struct snippetMatch *p = &pSnippet->aMatch[jj]; + if( p->iCol==pMatch->iCol && (( + p->iTerm==iNextTerm && + p->iToken>iEndToken && + p->iToken<=iEndToken+nNear + ) || ( + p->iTerm==iPrevTerm && + p->iTokeniToken>=iStartToken-nNear + ))){ + isOk = 1; + } + } + if( !isOk ){ + for(jj=1-pQueryTerm->iPhrase; jj<=0; jj++){ + pMatch[jj].iTerm = -1; + } + ii = -1; + iDir = 1; + } + } + } + iDir -= 2; + } +} + +/* +** Compute all offsets for the current row of the query. +** If the offsets have already been computed, this routine is a no-op. +*/ +static void snippetAllOffsets(fulltext_cursor *p){ + int nColumn; + int iColumn, i; + int iFirst, iLast; + fulltext_vtab *pFts; + + if( p->snippet.nMatch ) return; + if( p->q.nTerms==0 ) return; + pFts = p->q.pFts; + nColumn = pFts->nColumn; + iColumn = (p->iCursorType - QUERY_FULLTEXT); + if( iColumn<0 || iColumn>=nColumn ){ + iFirst = 0; + iLast = nColumn-1; + }else{ + iFirst = iColumn; + iLast = iColumn; + } + for(i=iFirst; i<=iLast; i++){ + const char *zDoc; + int nDoc; + zDoc = (const char*)sqlite3_column_text(p->pStmt, i+1); + nDoc = sqlite3_column_bytes(p->pStmt, i+1); + snippetOffsetsOfColumn(&p->q, &p->snippet, i, zDoc, nDoc); + } + + trimSnippetOffsetsForNear(&p->q, &p->snippet); +} + +/* +** Convert the information in the aMatch[] array of the snippet +** into the string zOffset[0..nOffset-1]. +*/ +static void snippetOffsetText(Snippet *p){ + int i; + int cnt = 0; + StringBuffer sb; + char zBuf[200]; + if( p->zOffset ) return; + initStringBuffer(&sb); + for(i=0; inMatch; i++){ + struct snippetMatch *pMatch = &p->aMatch[i]; + if( pMatch->iTerm>=0 ){ + /* If snippetMatch.iTerm is less than 0, then the match was + ** discarded as part of processing the NEAR operator (see the + ** trimSnippetOffsetsForNear() function for details). Ignore + ** it in this case + */ + zBuf[0] = ' '; + sprintf(&zBuf[cnt>0], "%d %d %d %d", pMatch->iCol, + pMatch->iTerm, pMatch->iStart, pMatch->nByte); + append(&sb, zBuf); + cnt++; + } + } + p->zOffset = stringBufferData(&sb); + p->nOffset = stringBufferLength(&sb); +} + +/* +** zDoc[0..nDoc-1] is phrase of text. aMatch[0..nMatch-1] are a set +** of matching words some of which might be in zDoc. zDoc is column +** number iCol. +** +** iBreak is suggested spot in zDoc where we could begin or end an +** excerpt. Return a value similar to iBreak but possibly adjusted +** to be a little left or right so that the break point is better. +*/ +static int wordBoundary( + int iBreak, /* The suggested break point */ + const char *zDoc, /* Document text */ + int nDoc, /* Number of bytes in zDoc[] */ + struct snippetMatch *aMatch, /* Matching words */ + int nMatch, /* Number of entries in aMatch[] */ + int iCol /* The column number for zDoc[] */ +){ + int i; + if( iBreak<=10 ){ + return 0; + } + if( iBreak>=nDoc-10 ){ + return nDoc; + } + for(i=0; i0 && aMatch[i-1].iStart+aMatch[i-1].nByte>=iBreak ){ + return aMatch[i-1].iStart; + } + } + for(i=1; i<=10; i++){ + if( safe_isspace(zDoc[iBreak-i]) ){ + return iBreak - i + 1; + } + if( safe_isspace(zDoc[iBreak+i]) ){ + return iBreak + i + 1; + } + } + return iBreak; +} + + + +/* +** Allowed values for Snippet.aMatch[].snStatus +*/ +#define SNIPPET_IGNORE 0 /* It is ok to omit this match from the snippet */ +#define SNIPPET_DESIRED 1 /* We want to include this match in the snippet */ + +/* +** Generate the text of a snippet. +*/ +static void snippetText( + fulltext_cursor *pCursor, /* The cursor we need the snippet for */ + const char *zStartMark, /* Markup to appear before each match */ + const char *zEndMark, /* Markup to appear after each match */ + const char *zEllipsis /* Ellipsis mark */ +){ + int i, j; + struct snippetMatch *aMatch; + int nMatch; + int nDesired; + StringBuffer sb; + int tailCol; + int tailOffset; + int iCol; + int nDoc; + const char *zDoc; + int iStart, iEnd; + int tailEllipsis = 0; + int iMatch; + + + sqlite3_free(pCursor->snippet.zSnippet); + pCursor->snippet.zSnippet = 0; + aMatch = pCursor->snippet.aMatch; + nMatch = pCursor->snippet.nMatch; + initStringBuffer(&sb); + + for(i=0; iq.nTerms; i++){ + for(j=0; j0; i++){ + if( aMatch[i].snStatus!=SNIPPET_DESIRED ) continue; + nDesired--; + iCol = aMatch[i].iCol; + zDoc = (const char*)sqlite3_column_text(pCursor->pStmt, iCol+1); + nDoc = sqlite3_column_bytes(pCursor->pStmt, iCol+1); + iStart = aMatch[i].iStart - 40; + iStart = wordBoundary(iStart, zDoc, nDoc, aMatch, nMatch, iCol); + if( iStart<=10 ){ + iStart = 0; + } + if( iCol==tailCol && iStart<=tailOffset+20 ){ + iStart = tailOffset; + } + if( (iCol!=tailCol && tailCol>=0) || iStart!=tailOffset ){ + trimWhiteSpace(&sb); + appendWhiteSpace(&sb); + append(&sb, zEllipsis); + appendWhiteSpace(&sb); + } + iEnd = aMatch[i].iStart + aMatch[i].nByte + 40; + iEnd = wordBoundary(iEnd, zDoc, nDoc, aMatch, nMatch, iCol); + if( iEnd>=nDoc-10 ){ + iEnd = nDoc; + tailEllipsis = 0; + }else{ + tailEllipsis = 1; + } + while( iMatchsnippet.zSnippet = stringBufferData(&sb); + pCursor->snippet.nSnippet = stringBufferLength(&sb); +} + + +/* +** Close the cursor. For additional information see the documentation +** on the xClose method of the virtual table interface. +*/ +static int fulltextClose(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + FTSTRACE(("FTS3 Close %p\n", c)); + sqlite3_finalize(c->pStmt); + queryClear(&c->q); + snippetClear(&c->snippet); + if( c->result.nData!=0 ) dlrDestroy(&c->reader); + dataBufferDestroy(&c->result); + sqlite3_free(c); + return SQLITE_OK; +} + +static int fulltextNext(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + int rc; + + FTSTRACE(("FTS3 Next %p\n", pCursor)); + snippetClear(&c->snippet); + if( c->iCursorType < QUERY_FULLTEXT ){ + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + switch( rc ){ + case SQLITE_ROW: + c->eof = 0; + return SQLITE_OK; + case SQLITE_DONE: + c->eof = 1; + return SQLITE_OK; + default: + c->eof = 1; + return rc; + } + } else { /* full-text query */ + rc = sqlite3_reset(c->pStmt); + if( rc!=SQLITE_OK ) return rc; + + if( c->result.nData==0 || dlrAtEnd(&c->reader) ){ + c->eof = 1; + return SQLITE_OK; + } + rc = sqlite3_bind_int64(c->pStmt, 1, dlrDocid(&c->reader)); + dlrStep(&c->reader); + if( rc!=SQLITE_OK ) return rc; + /* TODO(shess) Handle SQLITE_SCHEMA AND SQLITE_BUSY. */ + rc = sqlite3_step(c->pStmt); + if( rc==SQLITE_ROW ){ /* the case we expect */ + c->eof = 0; + return SQLITE_OK; + } + /* an error occurred; abort */ + return rc==SQLITE_DONE ? SQLITE_ERROR : rc; + } +} + + +/* TODO(shess) If we pushed LeafReader to the top of the file, or to +** another file, term_select() could be pushed above +** docListOfTerm(). +*/ +static int termSelect(fulltext_vtab *v, int iColumn, + const char *pTerm, int nTerm, int isPrefix, + DocListType iType, DataBuffer *out); + +/* Return a DocList corresponding to the query term *pTerm. If *pTerm +** is the first term of a phrase query, go ahead and evaluate the phrase +** query and return the doclist for the entire phrase query. +** +** The resulting DL_DOCIDS doclist is stored in pResult, which is +** overwritten. +*/ +static int docListOfTerm( + fulltext_vtab *v, /* The full text index */ + int iColumn, /* column to restrict to. No restriction if >=nColumn */ + QueryTerm *pQTerm, /* Term we are looking for, or 1st term of a phrase */ + DataBuffer *pResult /* Write the result here */ +){ + DataBuffer left, right, new; + int i, rc; + + /* No phrase search if no position info. */ + assert( pQTerm->nPhrase==0 || DL_DEFAULT!=DL_DOCIDS ); + + /* This code should never be called with buffered updates. */ + assert( v->nPendingData<0 ); + + dataBufferInit(&left, 0); + rc = termSelect(v, iColumn, pQTerm->pTerm, pQTerm->nTerm, pQTerm->isPrefix, + (0nPhrase ? DL_POSITIONS : DL_DOCIDS), &left); + if( rc ) return rc; + for(i=1; i<=pQTerm->nPhrase && left.nData>0; i++){ + /* If this token is connected to the next by a NEAR operator, and + ** the next token is the start of a phrase, then set nPhraseRight + ** to the number of tokens in the phrase. Otherwise leave it at 1. + */ + int nPhraseRight = 1; + while( (i+nPhraseRight)<=pQTerm->nPhrase + && pQTerm[i+nPhraseRight].nNear==0 + ){ + nPhraseRight++; + } + + dataBufferInit(&right, 0); + rc = termSelect(v, iColumn, pQTerm[i].pTerm, pQTerm[i].nTerm, + pQTerm[i].isPrefix, DL_POSITIONS, &right); + if( rc ){ + dataBufferDestroy(&left); + return rc; + } + dataBufferInit(&new, 0); + docListPhraseMerge(left.pData, left.nData, right.pData, right.nData, + pQTerm[i-1].nNear, pQTerm[i-1].iPhrase + nPhraseRight, + ((inPhrase) ? DL_POSITIONS : DL_DOCIDS), + &new); + dataBufferDestroy(&left); + dataBufferDestroy(&right); + left = new; + } + *pResult = left; + return SQLITE_OK; +} + +/* Add a new term pTerm[0..nTerm-1] to the query *q. +*/ +static void queryAdd(Query *q, const char *pTerm, int nTerm){ + QueryTerm *t; + ++q->nTerms; + q->pTerms = sqlite3_realloc(q->pTerms, q->nTerms * sizeof(q->pTerms[0])); + if( q->pTerms==0 ){ + q->nTerms = 0; + return; + } + t = &q->pTerms[q->nTerms - 1]; + CLEAR(t); + t->pTerm = sqlite3_malloc(nTerm+1); + memcpy(t->pTerm, pTerm, nTerm); + t->pTerm[nTerm] = 0; + t->nTerm = nTerm; + t->isOr = q->nextIsOr; + t->isPrefix = 0; + q->nextIsOr = 0; + t->iColumn = q->nextColumn; + q->nextColumn = q->dfltColumn; +} + +/* +** Check to see if the string zToken[0...nToken-1] matches any +** column name in the virtual table. If it does, +** return the zero-indexed column number. If not, return -1. +*/ +static int checkColumnSpecifier( + fulltext_vtab *pVtab, /* The virtual table */ + const char *zToken, /* Text of the token */ + int nToken /* Number of characters in the token */ +){ + int i; + for(i=0; inColumn; i++){ + if( memcmp(pVtab->azColumn[i], zToken, nToken)==0 + && pVtab->azColumn[i][nToken]==0 ){ + return i; + } + } + return -1; +} + +/* +** Parse the text at pSegment[0..nSegment-1]. Add additional terms +** to the query being assemblied in pQuery. +** +** inPhrase is true if pSegment[0..nSegement-1] is contained within +** double-quotes. If inPhrase is true, then the first term +** is marked with the number of terms in the phrase less one and +** OR and "-" syntax is ignored. If inPhrase is false, then every +** term found is marked with nPhrase=0 and OR and "-" syntax is significant. +*/ +static int tokenizeSegment( + sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */ + const char *pSegment, int nSegment, /* Query expression being parsed */ + int inPhrase, /* True if within "..." */ + Query *pQuery /* Append results here */ +){ + const sqlite3_tokenizer_module *pModule = pTokenizer->pModule; + sqlite3_tokenizer_cursor *pCursor; + int firstIndex = pQuery->nTerms; + int iCol; + int nTerm = 1; + + int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor); + if( rc!=SQLITE_OK ) return rc; + pCursor->pTokenizer = pTokenizer; + + while( 1 ){ + const char *pToken; + int nToken, iBegin, iEnd, iPos; + + rc = pModule->xNext(pCursor, + &pToken, &nToken, + &iBegin, &iEnd, &iPos); + if( rc!=SQLITE_OK ) break; + if( !inPhrase && + pSegment[iEnd]==':' && + (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){ + pQuery->nextColumn = iCol; + continue; + } + if( !inPhrase && pQuery->nTerms>0 && nToken==2 + && pSegment[iBegin+0]=='O' + && pSegment[iBegin+1]=='R' + ){ + pQuery->nextIsOr = 1; + continue; + } + if( !inPhrase && pQuery->nTerms>0 && !pQuery->nextIsOr && nToken==4 + && pSegment[iBegin+0]=='N' + && pSegment[iBegin+1]=='E' + && pSegment[iBegin+2]=='A' + && pSegment[iBegin+3]=='R' + ){ + QueryTerm *pTerm = &pQuery->pTerms[pQuery->nTerms-1]; + if( (iBegin+6)='0' && pSegment[iBegin+5]<='9' + ){ + pTerm->nNear = (pSegment[iBegin+5] - '0'); + nToken += 2; + if( pSegment[iBegin+6]>='0' && pSegment[iBegin+6]<=9 ){ + pTerm->nNear = pTerm->nNear * 10 + (pSegment[iBegin+6] - '0'); + iEnd++; + } + pModule->xNext(pCursor, &pToken, &nToken, &iBegin, &iEnd, &iPos); + } else { + pTerm->nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM; + } + pTerm->nNear++; + continue; + } + + queryAdd(pQuery, pToken, nToken); + if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){ + pQuery->pTerms[pQuery->nTerms-1].isNot = 1; + } + if( iEndpTerms[pQuery->nTerms-1].isPrefix = 1; + } + pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm; + if( inPhrase ){ + nTerm++; + } + } + + if( inPhrase && pQuery->nTerms>firstIndex ){ + pQuery->pTerms[firstIndex].nPhrase = pQuery->nTerms - firstIndex - 1; + } + + return pModule->xClose(pCursor); +} + +/* Parse a query string, yielding a Query object pQuery. +** +** The calling function will need to queryClear() to clean up +** the dynamically allocated memory held by pQuery. +*/ +static int parseQuery( + fulltext_vtab *v, /* The fulltext index */ + const char *zInput, /* Input text of the query string */ + int nInput, /* Size of the input text */ + int dfltColumn, /* Default column of the index to match against */ + Query *pQuery /* Write the parse results here. */ +){ + int iInput, inPhrase = 0; + int ii; + QueryTerm *aTerm; + + if( zInput==0 ) nInput = 0; + if( nInput<0 ) nInput = strlen(zInput); + pQuery->nTerms = 0; + pQuery->pTerms = NULL; + pQuery->nextIsOr = 0; + pQuery->nextColumn = dfltColumn; + pQuery->dfltColumn = dfltColumn; + pQuery->pFts = v; + + for(iInput=0; iInputiInput ){ + tokenizeSegment(v->pTokenizer, zInput+iInput, i-iInput, inPhrase, + pQuery); + } + iInput = i; + if( ipTerms; + for(ii=0; iinTerms; ii++){ + if( aTerm[ii].nNear || aTerm[ii].nPhrase ){ + while (aTerm[ii+aTerm[ii].nPhrase].nNear) { + aTerm[ii].nPhrase += (1 + aTerm[ii+aTerm[ii].nPhrase+1].nPhrase); + } + } + } + + return SQLITE_OK; +} + +/* TODO(shess) Refactor the code to remove this forward decl. */ +static int flushPendingTerms(fulltext_vtab *v); + +/* Perform a full-text query using the search expression in +** zInput[0..nInput-1]. Return a list of matching documents +** in pResult. +** +** Queries must match column iColumn. Or if iColumn>=nColumn +** they are allowed to match against any column. +*/ +static int fulltextQuery( + fulltext_vtab *v, /* The full text index */ + int iColumn, /* Match against this column by default */ + const char *zInput, /* The query string */ + int nInput, /* Number of bytes in zInput[] */ + DataBuffer *pResult, /* Write the result doclist here */ + Query *pQuery /* Put parsed query string here */ +){ + int i, iNext, rc; + DataBuffer left, right, or, new; + int nNot = 0; + QueryTerm *aTerm; + + /* TODO(shess) Instead of flushing pendingTerms, we could query for + ** the relevant term and merge the doclist into what we receive from + ** the database. Wait and see if this is a common issue, first. + ** + ** A good reason not to flush is to not generate update-related + ** error codes from here. + */ + + /* Flush any buffered updates before executing the query. */ + rc = flushPendingTerms(v); + if( rc!=SQLITE_OK ) return rc; + + /* TODO(shess) I think that the queryClear() calls below are not + ** necessary, because fulltextClose() already clears the query. + */ + rc = parseQuery(v, zInput, nInput, iColumn, pQuery); + if( rc!=SQLITE_OK ) return rc; + + /* Empty or NULL queries return no results. */ + if( pQuery->nTerms==0 ){ + dataBufferInit(pResult, 0); + return SQLITE_OK; + } + + /* Merge AND terms. */ + /* TODO(shess) I think we can early-exit if( i>nNot && left.nData==0 ). */ + aTerm = pQuery->pTerms; + for(i = 0; inTerms; i=iNext){ + if( aTerm[i].isNot ){ + /* Handle all NOT terms in a separate pass */ + nNot++; + iNext = i + aTerm[i].nPhrase+1; + continue; + } + iNext = i + aTerm[i].nPhrase + 1; + rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); + if( rc ){ + if( i!=nNot ) dataBufferDestroy(&left); + queryClear(pQuery); + return rc; + } + while( iNextnTerms && aTerm[iNext].isOr ){ + rc = docListOfTerm(v, aTerm[iNext].iColumn, &aTerm[iNext], &or); + iNext += aTerm[iNext].nPhrase + 1; + if( rc ){ + if( i!=nNot ) dataBufferDestroy(&left); + dataBufferDestroy(&right); + queryClear(pQuery); + return rc; + } + dataBufferInit(&new, 0); + docListOrMerge(right.pData, right.nData, or.pData, or.nData, &new); + dataBufferDestroy(&right); + dataBufferDestroy(&or); + right = new; + } + if( i==nNot ){ /* first term processed. */ + left = right; + }else{ + dataBufferInit(&new, 0); + docListAndMerge(left.pData, left.nData, right.pData, right.nData, &new); + dataBufferDestroy(&right); + dataBufferDestroy(&left); + left = new; + } + } + + if( nNot==pQuery->nTerms ){ + /* We do not yet know how to handle a query of only NOT terms */ + return SQLITE_ERROR; + } + + /* Do the EXCEPT terms */ + for(i=0; inTerms; i += aTerm[i].nPhrase + 1){ + if( !aTerm[i].isNot ) continue; + rc = docListOfTerm(v, aTerm[i].iColumn, &aTerm[i], &right); + if( rc ){ + queryClear(pQuery); + dataBufferDestroy(&left); + return rc; + } + dataBufferInit(&new, 0); + docListExceptMerge(left.pData, left.nData, right.pData, right.nData, &new); + dataBufferDestroy(&right); + dataBufferDestroy(&left); + left = new; + } + + *pResult = left; + return rc; +} + +/* +** This is the xFilter interface for the virtual table. See +** the virtual table xFilter method documentation for additional +** information. +** +** If idxNum==QUERY_GENERIC then do a full table scan against +** the %_content table. +** +** If idxNum==QUERY_DOCID then do a docid lookup for a single entry +** in the %_content table. +** +** If idxNum>=QUERY_FULLTEXT then use the full text index. The +** column on the left-hand side of the MATCH operator is column +** number idxNum-QUERY_FULLTEXT, 0 indexed. argv[0] is the right-hand +** side of the MATCH operator. +*/ +/* TODO(shess) Upgrade the cursor initialization and destruction to +** account for fulltextFilter() being called multiple times on the +** same cursor. The current solution is very fragile. Apply fix to +** fts3 as appropriate. +*/ +static int fulltextFilter( + sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ + int idxNum, const char *idxStr, /* Which indexing scheme to use */ + int argc, sqlite3_value **argv /* Arguments for the indexing scheme */ +){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + fulltext_vtab *v = cursor_vtab(c); + int rc; + StringBuffer sb; + + FTSTRACE(("FTS3 Filter %p\n",pCursor)); + + initStringBuffer(&sb); + append(&sb, "SELECT docid, "); + appendList(&sb, v->nColumn, v->azContentColumn); + append(&sb, " FROM %_content"); + if( idxNum!=QUERY_GENERIC ) append(&sb, " WHERE docid = ?"); + sqlite3_finalize(c->pStmt); + rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, stringBufferData(&sb)); + stringBufferDestroy(&sb); + if( rc!=SQLITE_OK ) return rc; + + c->iCursorType = idxNum; + switch( idxNum ){ + case QUERY_GENERIC: + break; + + case QUERY_DOCID: + rc = sqlite3_bind_int64(c->pStmt, 1, sqlite3_value_int64(argv[0])); + if( rc!=SQLITE_OK ) return rc; + break; + + default: /* full-text search */ + { + const char *zQuery = (const char *)sqlite3_value_text(argv[0]); + assert( idxNum<=QUERY_FULLTEXT+v->nColumn); + assert( argc==1 ); + queryClear(&c->q); + if( c->result.nData!=0 ){ + /* This case happens if the same cursor is used repeatedly. */ + dlrDestroy(&c->reader); + dataBufferReset(&c->result); + }else{ + dataBufferInit(&c->result, 0); + } + rc = fulltextQuery(v, idxNum-QUERY_FULLTEXT, zQuery, -1, &c->result, &c->q); + if( rc!=SQLITE_OK ) return rc; + if( c->result.nData!=0 ){ + dlrInit(&c->reader, DL_DOCIDS, c->result.pData, c->result.nData); + } + break; + } + } + + return fulltextNext(pCursor); +} + +/* This is the xEof method of the virtual table. The SQLite core +** calls this routine to find out if it has reached the end of +** a query's results set. +*/ +static int fulltextEof(sqlite3_vtab_cursor *pCursor){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + return c->eof; +} + +/* This is the xColumn method of the virtual table. The SQLite +** core calls this method during a query when it needs the value +** of a column from the virtual table. This method needs to use +** one of the sqlite3_result_*() routines to store the requested +** value back in the pContext. +*/ +static int fulltextColumn(sqlite3_vtab_cursor *pCursor, + sqlite3_context *pContext, int idxCol){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + fulltext_vtab *v = cursor_vtab(c); + + if( idxColnColumn ){ + sqlite3_value *pVal = sqlite3_column_value(c->pStmt, idxCol+1); + sqlite3_result_value(pContext, pVal); + }else if( idxCol==v->nColumn ){ + /* The extra column whose name is the same as the table. + ** Return a blob which is a pointer to the cursor + */ + sqlite3_result_blob(pContext, &c, sizeof(c), SQLITE_TRANSIENT); + }else if( idxCol==v->nColumn+1 ){ + /* The docid column, which is an alias for rowid. */ + sqlite3_value *pVal = sqlite3_column_value(c->pStmt, 0); + sqlite3_result_value(pContext, pVal); + } + 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. fts3 +** exposes %_content.docid as the rowid for the virtual table. The +** rowid should be written to *pRowid. +*/ +static int fulltextRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ + fulltext_cursor *c = (fulltext_cursor *) pCursor; + + *pRowid = sqlite3_column_int64(c->pStmt, 0); + return SQLITE_OK; +} + +/* Add all terms in [zText] to pendingTerms table. If [iColumn] > 0, +** we also store positions and offsets in the hash table using that +** column number. +*/ +static int buildTerms(fulltext_vtab *v, sqlite_int64 iDocid, + const char *zText, int iColumn){ + sqlite3_tokenizer *pTokenizer = v->pTokenizer; + sqlite3_tokenizer_cursor *pCursor; + const char *pToken; + int nTokenBytes; + int iStartOffset, iEndOffset, iPosition; + int rc; + + rc = pTokenizer->pModule->xOpen(pTokenizer, zText, -1, &pCursor); + if( rc!=SQLITE_OK ) return rc; + + pCursor->pTokenizer = pTokenizer; + while( SQLITE_OK==(rc=pTokenizer->pModule->xNext(pCursor, + &pToken, &nTokenBytes, + &iStartOffset, &iEndOffset, + &iPosition)) ){ + DLCollector *p; + int nData; /* Size of doclist before our update. */ + + /* Positions can't be negative; we use -1 as a terminator + * internally. Token can't be NULL or empty. */ + if( iPosition<0 || pToken == NULL || nTokenBytes == 0 ){ + rc = SQLITE_ERROR; + break; + } + + p = fts3HashFind(&v->pendingTerms, pToken, nTokenBytes); + if( p==NULL ){ + nData = 0; + p = dlcNew(iDocid, DL_DEFAULT); + fts3HashInsert(&v->pendingTerms, pToken, nTokenBytes, p); + + /* Overhead for our hash table entry, the key, and the value. */ + v->nPendingData += sizeof(struct fts3HashElem)+sizeof(*p)+nTokenBytes; + }else{ + nData = p->b.nData; + if( p->dlw.iPrevDocid!=iDocid ) dlcNext(p, iDocid); + } + if( iColumn>=0 ){ + dlcAddPos(p, iColumn, iPosition, iStartOffset, iEndOffset); + } + + /* Accumulate data added by dlcNew or dlcNext, and dlcAddPos. */ + v->nPendingData += p->b.nData-nData; + } + + /* TODO(shess) Check return? Should this be able to cause errors at + ** this point? Actually, same question about sqlite3_finalize(), + ** though one could argue that failure there means that the data is + ** not durable. *ponder* + */ + pTokenizer->pModule->xClose(pCursor); + if( SQLITE_DONE == rc ) return SQLITE_OK; + return rc; +} + +/* Add doclists for all terms in [pValues] to pendingTerms table. */ +static int insertTerms(fulltext_vtab *v, sqlite_int64 iDocid, + sqlite3_value **pValues){ + int i; + for(i = 0; i < v->nColumn ; ++i){ + char *zText = (char*)sqlite3_value_text(pValues[i]); + int rc = buildTerms(v, iDocid, zText, i); + if( rc!=SQLITE_OK ) return rc; + } + return SQLITE_OK; +} + +/* Add empty doclists for all terms in the given row's content to +** pendingTerms. +*/ +static int deleteTerms(fulltext_vtab *v, sqlite_int64 iDocid){ + const char **pValues; + int i, rc; + + /* TODO(shess) Should we allow such tables at all? */ + if( DL_DEFAULT==DL_DOCIDS ) return SQLITE_ERROR; + + rc = content_select(v, iDocid, &pValues); + if( rc!=SQLITE_OK ) return rc; + + for(i = 0 ; i < v->nColumn; ++i) { + rc = buildTerms(v, iDocid, pValues[i], -1); + if( rc!=SQLITE_OK ) break; + } + + freeStringArray(v->nColumn, pValues); + return SQLITE_OK; +} + +/* TODO(shess) Refactor the code to remove this forward decl. */ +static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid); + +/* Insert a row into the %_content table; set *piDocid to be the ID of the +** new row. Add doclists for terms to pendingTerms. +*/ +static int index_insert(fulltext_vtab *v, sqlite3_value *pRequestDocid, + sqlite3_value **pValues, sqlite_int64 *piDocid){ + int rc; + + rc = content_insert(v, pRequestDocid, pValues); /* execute an SQL INSERT */ + if( rc!=SQLITE_OK ) return rc; + + /* docid column is an alias for rowid. */ + *piDocid = sqlite3_last_insert_rowid(v->db); + rc = initPendingTerms(v, *piDocid); + if( rc!=SQLITE_OK ) return rc; + + return insertTerms(v, *piDocid, pValues); +} + +/* Delete a row from the %_content table; add empty doclists for terms +** to pendingTerms. +*/ +static int index_delete(fulltext_vtab *v, sqlite_int64 iRow){ + int rc = initPendingTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = deleteTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + return content_delete(v, iRow); /* execute an SQL DELETE */ +} + +/* Update a row in the %_content table; add delete doclists to +** pendingTerms for old terms not in the new data, add insert doclists +** to pendingTerms for terms in the new data. +*/ +static int index_update(fulltext_vtab *v, sqlite_int64 iRow, + sqlite3_value **pValues){ + int rc = initPendingTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + /* Generate an empty doclist for each term that previously appeared in this + * row. */ + rc = deleteTerms(v, iRow); + if( rc!=SQLITE_OK ) return rc; + + rc = content_update(v, pValues, iRow); /* execute an SQL UPDATE */ + if( rc!=SQLITE_OK ) return rc; + + /* Now add positions for terms which appear in the updated row. */ + return insertTerms(v, iRow, pValues); +} + +/*******************************************************************/ +/* InteriorWriter is used to collect terms and block references into +** interior nodes in %_segments. See commentary at top of file for +** format. +*/ + +/* How large interior nodes can grow. */ +#define INTERIOR_MAX 2048 + +/* Minimum number of terms per interior node (except the root). This +** prevents large terms from making the tree too skinny - must be >0 +** so that the tree always makes progress. Note that the min tree +** fanout will be INTERIOR_MIN_TERMS+1. +*/ +#define INTERIOR_MIN_TERMS 7 +#if INTERIOR_MIN_TERMS<1 +# error INTERIOR_MIN_TERMS must be greater than 0. +#endif + +/* ROOT_MAX controls how much data is stored inline in the segment +** directory. +*/ +/* TODO(shess) Push ROOT_MAX down to whoever is writing things. It's +** only here so that interiorWriterRootInfo() and leafWriterRootInfo() +** can both see it, but if the caller passed it in, we wouldn't even +** need a define. +*/ +#define ROOT_MAX 1024 +#if ROOT_MAXterm, 0); + dataBufferReplace(&block->term, pTerm, nTerm); + + n = fts3PutVarint(c, iHeight); + n += fts3PutVarint(c+n, iChildBlock); + dataBufferInit(&block->data, INTERIOR_MAX); + dataBufferReplace(&block->data, c, n); + } + return block; +} + +#ifndef NDEBUG +/* Verify that the data is readable as an interior node. */ +static void interiorBlockValidate(InteriorBlock *pBlock){ + const char *pData = pBlock->data.pData; + int nData = pBlock->data.nData; + int n, iDummy; + sqlite_int64 iBlockid; + + assert( nData>0 ); + assert( pData!=0 ); + assert( pData+nData>pData ); + + /* Must lead with height of node as a varint(n), n>0 */ + n = fts3GetVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>0 ); + assert( n0 ); + assert( n<=nData ); + pData += n; + nData -= n; + + /* Zero or more terms of positive length */ + if( nData!=0 ){ + /* First term is not delta-encoded. */ + n = fts3GetVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>0 ); + assert( n+iDummy>0); + assert( n+iDummy<=nData ); + pData += n+iDummy; + nData -= n+iDummy; + + /* Following terms delta-encoded. */ + while( nData!=0 ){ + /* Length of shared prefix. */ + n = fts3GetVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>=0 ); + assert( n0 ); + assert( iDummy>0 ); + assert( n+iDummy>0); + assert( n+iDummy<=nData ); + pData += n+iDummy; + nData -= n+iDummy; + } + } +} +#define ASSERT_VALID_INTERIOR_BLOCK(x) interiorBlockValidate(x) +#else +#define ASSERT_VALID_INTERIOR_BLOCK(x) assert( 1 ) +#endif + +typedef struct InteriorWriter { + int iHeight; /* from 0 at leaves. */ + InteriorBlock *first, *last; + struct InteriorWriter *parentWriter; + + DataBuffer term; /* Last term written to block "last". */ + sqlite_int64 iOpeningChildBlock; /* First child block in block "last". */ +#ifndef NDEBUG + sqlite_int64 iLastChildBlock; /* for consistency checks. */ +#endif +} InteriorWriter; + +/* Initialize an interior node where pTerm[nTerm] marks the leftmost +** term in the tree. iChildBlock is the leftmost child block at the +** next level down the tree. +*/ +static void interiorWriterInit(int iHeight, const char *pTerm, int nTerm, + sqlite_int64 iChildBlock, + InteriorWriter *pWriter){ + InteriorBlock *block; + assert( iHeight>0 ); + CLEAR(pWriter); + + pWriter->iHeight = iHeight; + pWriter->iOpeningChildBlock = iChildBlock; +#ifndef NDEBUG + pWriter->iLastChildBlock = iChildBlock; +#endif + block = interiorBlockNew(iHeight, iChildBlock, pTerm, nTerm); + pWriter->last = pWriter->first = block; + ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); + dataBufferInit(&pWriter->term, 0); +} + +/* Append the child node rooted at iChildBlock to the interior node, +** with pTerm[nTerm] as the leftmost term in iChildBlock's subtree. +*/ +static void interiorWriterAppend(InteriorWriter *pWriter, + const char *pTerm, int nTerm, + sqlite_int64 iChildBlock){ + char c[VARINT_MAX+VARINT_MAX]; + int n, nPrefix = 0; + + ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); + + /* The first term written into an interior node is actually + ** associated with the second child added (the first child was added + ** in interiorWriterInit, or in the if clause at the bottom of this + ** function). That term gets encoded straight up, with nPrefix left + ** at 0. + */ + if( pWriter->term.nData==0 ){ + n = fts3PutVarint(c, nTerm); + }else{ + while( nPrefixterm.nData && + pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){ + nPrefix++; + } + + n = fts3PutVarint(c, nPrefix); + n += fts3PutVarint(c+n, nTerm-nPrefix); + } + +#ifndef NDEBUG + pWriter->iLastChildBlock++; +#endif + assert( pWriter->iLastChildBlock==iChildBlock ); + + /* Overflow to a new block if the new term makes the current block + ** too big, and the current block already has enough terms. + */ + if( pWriter->last->data.nData+n+nTerm-nPrefix>INTERIOR_MAX && + iChildBlock-pWriter->iOpeningChildBlock>INTERIOR_MIN_TERMS ){ + pWriter->last->next = interiorBlockNew(pWriter->iHeight, iChildBlock, + pTerm, nTerm); + pWriter->last = pWriter->last->next; + pWriter->iOpeningChildBlock = iChildBlock; + dataBufferReset(&pWriter->term); + }else{ + dataBufferAppend2(&pWriter->last->data, c, n, + pTerm+nPrefix, nTerm-nPrefix); + dataBufferReplace(&pWriter->term, pTerm, nTerm); + } + ASSERT_VALID_INTERIOR_BLOCK(pWriter->last); +} + +/* Free the space used by pWriter, including the linked-list of +** InteriorBlocks, and parentWriter, if present. +*/ +static int interiorWriterDestroy(InteriorWriter *pWriter){ + InteriorBlock *block = pWriter->first; + + while( block!=NULL ){ + InteriorBlock *b = block; + block = block->next; + dataBufferDestroy(&b->term); + dataBufferDestroy(&b->data); + sqlite3_free(b); + } + if( pWriter->parentWriter!=NULL ){ + interiorWriterDestroy(pWriter->parentWriter); + sqlite3_free(pWriter->parentWriter); + } + dataBufferDestroy(&pWriter->term); + SCRAMBLE(pWriter); + return SQLITE_OK; +} + +/* If pWriter can fit entirely in ROOT_MAX, return it as the root info +** directly, leaving *piEndBlockid unchanged. Otherwise, flush +** pWriter to %_segments, building a new layer of interior nodes, and +** recursively ask for their root into. +*/ +static int interiorWriterRootInfo(fulltext_vtab *v, InteriorWriter *pWriter, + char **ppRootInfo, int *pnRootInfo, + sqlite_int64 *piEndBlockid){ + InteriorBlock *block = pWriter->first; + sqlite_int64 iBlockid = 0; + int rc; + + /* If we can fit the segment inline */ + if( block==pWriter->last && block->data.nDatadata.pData; + *pnRootInfo = block->data.nData; + return SQLITE_OK; + } + + /* Flush the first block to %_segments, and create a new level of + ** interior node. + */ + ASSERT_VALID_INTERIOR_BLOCK(block); + rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); + if( rc!=SQLITE_OK ) return rc; + *piEndBlockid = iBlockid; + + pWriter->parentWriter = sqlite3_malloc(sizeof(*pWriter->parentWriter)); + interiorWriterInit(pWriter->iHeight+1, + block->term.pData, block->term.nData, + iBlockid, pWriter->parentWriter); + + /* Flush additional blocks and append to the higher interior + ** node. + */ + for(block=block->next; block!=NULL; block=block->next){ + ASSERT_VALID_INTERIOR_BLOCK(block); + rc = block_insert(v, block->data.pData, block->data.nData, &iBlockid); + if( rc!=SQLITE_OK ) return rc; + *piEndBlockid = iBlockid; + + interiorWriterAppend(pWriter->parentWriter, + block->term.pData, block->term.nData, iBlockid); + } + + /* Parent node gets the chance to be the root. */ + return interiorWriterRootInfo(v, pWriter->parentWriter, + ppRootInfo, pnRootInfo, piEndBlockid); +} + +/****************************************************************/ +/* InteriorReader is used to read off the data from an interior node +** (see comment at top of file for the format). +*/ +typedef struct InteriorReader { + const char *pData; + int nData; + + DataBuffer term; /* previous term, for decoding term delta. */ + + sqlite_int64 iBlockid; +} InteriorReader; + +static void interiorReaderDestroy(InteriorReader *pReader){ + dataBufferDestroy(&pReader->term); + SCRAMBLE(pReader); +} + +/* TODO(shess) The assertions are great, but what if we're in NDEBUG +** and the blob is empty or otherwise contains suspect data? +*/ +static void interiorReaderInit(const char *pData, int nData, + InteriorReader *pReader){ + int n, nTerm; + + /* Require at least the leading flag byte */ + assert( nData>0 ); + assert( pData[0]!='\0' ); + + CLEAR(pReader); + + /* Decode the base blockid, and set the cursor to the first term. */ + n = fts3GetVarint(pData+1, &pReader->iBlockid); + assert( 1+n<=nData ); + pReader->pData = pData+1+n; + pReader->nData = nData-(1+n); + + /* A single-child interior node (such as when a leaf node was too + ** large for the segment directory) won't have any terms. + ** Otherwise, decode the first term. + */ + if( pReader->nData==0 ){ + dataBufferInit(&pReader->term, 0); + }else{ + n = fts3GetVarint32(pReader->pData, &nTerm); + dataBufferInit(&pReader->term, nTerm); + dataBufferReplace(&pReader->term, pReader->pData+n, nTerm); + assert( n+nTerm<=pReader->nData ); + pReader->pData += n+nTerm; + pReader->nData -= n+nTerm; + } +} + +static int interiorReaderAtEnd(InteriorReader *pReader){ + return pReader->term.nData==0; +} + +static sqlite_int64 interiorReaderCurrentBlockid(InteriorReader *pReader){ + return pReader->iBlockid; +} + +static int interiorReaderTermBytes(InteriorReader *pReader){ + assert( !interiorReaderAtEnd(pReader) ); + return pReader->term.nData; +} +static const char *interiorReaderTerm(InteriorReader *pReader){ + assert( !interiorReaderAtEnd(pReader) ); + return pReader->term.pData; +} + +/* Step forward to the next term in the node. */ +static void interiorReaderStep(InteriorReader *pReader){ + assert( !interiorReaderAtEnd(pReader) ); + + /* If the last term has been read, signal eof, else construct the + ** next term. + */ + if( pReader->nData==0 ){ + dataBufferReset(&pReader->term); + }else{ + int n, nPrefix, nSuffix; + + n = fts3GetVarint32(pReader->pData, &nPrefix); + n += fts3GetVarint32(pReader->pData+n, &nSuffix); + + /* Truncate the current term and append suffix data. */ + pReader->term.nData = nPrefix; + dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); + + assert( n+nSuffix<=pReader->nData ); + pReader->pData += n+nSuffix; + pReader->nData -= n+nSuffix; + } + pReader->iBlockid++; +} + +/* Compare the current term to pTerm[nTerm], returning strcmp-style +** results. If isPrefix, equality means equal through nTerm bytes. +*/ +static int interiorReaderTermCmp(InteriorReader *pReader, + const char *pTerm, int nTerm, int isPrefix){ + const char *pReaderTerm = interiorReaderTerm(pReader); + int nReaderTerm = interiorReaderTermBytes(pReader); + int c, n = nReaderTerm0 ) return -1; + if( nTerm>0 ) return 1; + return 0; + } + + c = memcmp(pReaderTerm, pTerm, n); + if( c!=0 ) return c; + if( isPrefix && n==nTerm ) return 0; + return nReaderTerm - nTerm; +} + +/****************************************************************/ +/* LeafWriter is used to collect terms and associated doclist data +** into leaf blocks in %_segments (see top of file for format info). +** Expected usage is: +** +** LeafWriter writer; +** leafWriterInit(0, 0, &writer); +** while( sorted_terms_left_to_process ){ +** // data is doclist data for that term. +** rc = leafWriterStep(v, &writer, pTerm, nTerm, pData, nData); +** if( rc!=SQLITE_OK ) goto err; +** } +** rc = leafWriterFinalize(v, &writer); +**err: +** leafWriterDestroy(&writer); +** return rc; +** +** leafWriterStep() may write a collected leaf out to %_segments. +** leafWriterFinalize() finishes writing any buffered data and stores +** a root node in %_segdir. leafWriterDestroy() frees all buffers and +** InteriorWriters allocated as part of writing this segment. +** +** TODO(shess) Document leafWriterStepMerge(). +*/ + +/* Put terms with data this big in their own block. */ +#define STANDALONE_MIN 1024 + +/* Keep leaf blocks below this size. */ +#define LEAF_MAX 2048 + +typedef struct LeafWriter { + int iLevel; + int idx; + sqlite_int64 iStartBlockid; /* needed to create the root info */ + sqlite_int64 iEndBlockid; /* when we're done writing. */ + + DataBuffer term; /* previous encoded term */ + DataBuffer data; /* encoding buffer */ + + /* bytes of first term in the current node which distinguishes that + ** term from the last term of the previous node. + */ + int nTermDistinct; + + InteriorWriter parentWriter; /* if we overflow */ + int has_parent; +} LeafWriter; + +static void leafWriterInit(int iLevel, int idx, LeafWriter *pWriter){ + CLEAR(pWriter); + pWriter->iLevel = iLevel; + pWriter->idx = idx; + + dataBufferInit(&pWriter->term, 32); + + /* Start out with a reasonably sized block, though it can grow. */ + dataBufferInit(&pWriter->data, LEAF_MAX); +} + +#ifndef NDEBUG +/* Verify that the data is readable as a leaf node. */ +static void leafNodeValidate(const char *pData, int nData){ + int n, iDummy; + + if( nData==0 ) return; + assert( nData>0 ); + assert( pData!=0 ); + assert( pData+nData>pData ); + + /* Must lead with a varint(0) */ + n = fts3GetVarint32(pData, &iDummy); + assert( iDummy==0 ); + assert( n>0 ); + assert( n0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy<=nData ); + ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL); + pData += n+iDummy; + nData -= n+iDummy; + + /* Verify that trailing terms and doclists also are readable. */ + while( nData!=0 ){ + n = fts3GetVarint32(pData, &iDummy); + assert( n>0 ); + assert( iDummy>=0 ); + assert( n0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy0 ); + assert( iDummy>0 ); + assert( n+iDummy>0 ); + assert( n+iDummy<=nData ); + ASSERT_VALID_DOCLIST(DL_DEFAULT, pData+n, iDummy, NULL); + pData += n+iDummy; + nData -= n+iDummy; + } +} +#define ASSERT_VALID_LEAF_NODE(p, n) leafNodeValidate(p, n) +#else +#define ASSERT_VALID_LEAF_NODE(p, n) assert( 1 ) +#endif + +/* Flush the current leaf node to %_segments, and adding the resulting +** blockid and the starting term to the interior node which will +** contain it. +*/ +static int leafWriterInternalFlush(fulltext_vtab *v, LeafWriter *pWriter, + int iData, int nData){ + sqlite_int64 iBlockid = 0; + const char *pStartingTerm; + int nStartingTerm, rc, n; + + /* Must have the leading varint(0) flag, plus at least some + ** valid-looking data. + */ + assert( nData>2 ); + assert( iData>=0 ); + assert( iData+nData<=pWriter->data.nData ); + ASSERT_VALID_LEAF_NODE(pWriter->data.pData+iData, nData); + + rc = block_insert(v, pWriter->data.pData+iData, nData, &iBlockid); + if( rc!=SQLITE_OK ) return rc; + assert( iBlockid!=0 ); + + /* Reconstruct the first term in the leaf for purposes of building + ** the interior node. + */ + n = fts3GetVarint32(pWriter->data.pData+iData+1, &nStartingTerm); + pStartingTerm = pWriter->data.pData+iData+1+n; + assert( pWriter->data.nData>iData+1+n+nStartingTerm ); + assert( pWriter->nTermDistinct>0 ); + assert( pWriter->nTermDistinct<=nStartingTerm ); + nStartingTerm = pWriter->nTermDistinct; + + if( pWriter->has_parent ){ + interiorWriterAppend(&pWriter->parentWriter, + pStartingTerm, nStartingTerm, iBlockid); + }else{ + interiorWriterInit(1, pStartingTerm, nStartingTerm, iBlockid, + &pWriter->parentWriter); + pWriter->has_parent = 1; + } + + /* Track the span of this segment's leaf nodes. */ + if( pWriter->iEndBlockid==0 ){ + pWriter->iEndBlockid = pWriter->iStartBlockid = iBlockid; + }else{ + pWriter->iEndBlockid++; + assert( iBlockid==pWriter->iEndBlockid ); + } + + return SQLITE_OK; +} +static int leafWriterFlush(fulltext_vtab *v, LeafWriter *pWriter){ + int rc = leafWriterInternalFlush(v, pWriter, 0, pWriter->data.nData); + if( rc!=SQLITE_OK ) return rc; + + /* Re-initialize the output buffer. */ + dataBufferReset(&pWriter->data); + + return SQLITE_OK; +} + +/* Fetch the root info for the segment. If the entire leaf fits +** within ROOT_MAX, then it will be returned directly, otherwise it +** will be flushed and the root info will be returned from the +** interior node. *piEndBlockid is set to the blockid of the last +** interior or leaf node written to disk (0 if none are written at +** all). +*/ +static int leafWriterRootInfo(fulltext_vtab *v, LeafWriter *pWriter, + char **ppRootInfo, int *pnRootInfo, + sqlite_int64 *piEndBlockid){ + /* we can fit the segment entirely inline */ + if( !pWriter->has_parent && pWriter->data.nDatadata.pData; + *pnRootInfo = pWriter->data.nData; + *piEndBlockid = 0; + return SQLITE_OK; + } + + /* Flush remaining leaf data. */ + if( pWriter->data.nData>0 ){ + int rc = leafWriterFlush(v, pWriter); + if( rc!=SQLITE_OK ) return rc; + } + + /* We must have flushed a leaf at some point. */ + assert( pWriter->has_parent ); + + /* Tenatively set the end leaf blockid as the end blockid. If the + ** interior node can be returned inline, this will be the final + ** blockid, otherwise it will be overwritten by + ** interiorWriterRootInfo(). + */ + *piEndBlockid = pWriter->iEndBlockid; + + return interiorWriterRootInfo(v, &pWriter->parentWriter, + ppRootInfo, pnRootInfo, piEndBlockid); +} + +/* Collect the rootInfo data and store it into the segment directory. +** This has the effect of flushing the segment's leaf data to +** %_segments, and also flushing any interior nodes to %_segments. +*/ +static int leafWriterFinalize(fulltext_vtab *v, LeafWriter *pWriter){ + sqlite_int64 iEndBlockid; + char *pRootInfo; + int rc, nRootInfo; + + rc = leafWriterRootInfo(v, pWriter, &pRootInfo, &nRootInfo, &iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + /* Don't bother storing an entirely empty segment. */ + if( iEndBlockid==0 && nRootInfo==0 ) return SQLITE_OK; + + return segdir_set(v, pWriter->iLevel, pWriter->idx, + pWriter->iStartBlockid, pWriter->iEndBlockid, + iEndBlockid, pRootInfo, nRootInfo); +} + +static void leafWriterDestroy(LeafWriter *pWriter){ + if( pWriter->has_parent ) interiorWriterDestroy(&pWriter->parentWriter); + dataBufferDestroy(&pWriter->term); + dataBufferDestroy(&pWriter->data); +} + +/* Encode a term into the leafWriter, delta-encoding as appropriate. +** Returns the length of the new term which distinguishes it from the +** previous term, which can be used to set nTermDistinct when a node +** boundary is crossed. +*/ +static int leafWriterEncodeTerm(LeafWriter *pWriter, + const char *pTerm, int nTerm){ + char c[VARINT_MAX+VARINT_MAX]; + int n, nPrefix = 0; + + assert( nTerm>0 ); + while( nPrefixterm.nData && + pTerm[nPrefix]==pWriter->term.pData[nPrefix] ){ + nPrefix++; + /* Failing this implies that the terms weren't in order. */ + assert( nPrefixdata.nData==0 ){ + /* Encode the node header and leading term as: + ** varint(0) + ** varint(nTerm) + ** char pTerm[nTerm] + */ + n = fts3PutVarint(c, '\0'); + n += fts3PutVarint(c+n, nTerm); + dataBufferAppend2(&pWriter->data, c, n, pTerm, nTerm); + }else{ + /* Delta-encode the term as: + ** varint(nPrefix) + ** varint(nSuffix) + ** char pTermSuffix[nSuffix] + */ + n = fts3PutVarint(c, nPrefix); + n += fts3PutVarint(c+n, nTerm-nPrefix); + dataBufferAppend2(&pWriter->data, c, n, pTerm+nPrefix, nTerm-nPrefix); + } + dataBufferReplace(&pWriter->term, pTerm, nTerm); + + return nPrefix+1; +} + +/* Used to avoid a memmove when a large amount of doclist data is in +** the buffer. This constructs a node and term header before +** iDoclistData and flushes the resulting complete node using +** leafWriterInternalFlush(). +*/ +static int leafWriterInlineFlush(fulltext_vtab *v, LeafWriter *pWriter, + const char *pTerm, int nTerm, + int iDoclistData){ + char c[VARINT_MAX+VARINT_MAX]; + int iData, n = fts3PutVarint(c, 0); + n += fts3PutVarint(c+n, nTerm); + + /* There should always be room for the header. Even if pTerm shared + ** a substantial prefix with the previous term, the entire prefix + ** could be constructed from earlier data in the doclist, so there + ** should be room. + */ + assert( iDoclistData>=n+nTerm ); + + iData = iDoclistData-(n+nTerm); + memcpy(pWriter->data.pData+iData, c, n); + memcpy(pWriter->data.pData+iData+n, pTerm, nTerm); + + return leafWriterInternalFlush(v, pWriter, iData, pWriter->data.nData-iData); +} + +/* Push pTerm[nTerm] along with the doclist data to the leaf layer of +** %_segments. +*/ +static int leafWriterStepMerge(fulltext_vtab *v, LeafWriter *pWriter, + const char *pTerm, int nTerm, + DLReader *pReaders, int nReaders){ + char c[VARINT_MAX+VARINT_MAX]; + int iTermData = pWriter->data.nData, iDoclistData; + int i, nData, n, nActualData, nActual, rc, nTermDistinct; + + ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData); + nTermDistinct = leafWriterEncodeTerm(pWriter, pTerm, nTerm); + + /* Remember nTermDistinct if opening a new node. */ + if( iTermData==0 ) pWriter->nTermDistinct = nTermDistinct; + + iDoclistData = pWriter->data.nData; + + /* Estimate the length of the merged doclist so we can leave space + ** to encode it. + */ + for(i=0, nData=0; idata, c, n); + + docListMerge(&pWriter->data, pReaders, nReaders); + ASSERT_VALID_DOCLIST(DL_DEFAULT, + pWriter->data.pData+iDoclistData+n, + pWriter->data.nData-iDoclistData-n, NULL); + + /* The actual amount of doclist data at this point could be smaller + ** than the length we encoded. Additionally, the space required to + ** encode this length could be smaller. For small doclists, this is + ** not a big deal, we can just use memmove() to adjust things. + */ + nActualData = pWriter->data.nData-(iDoclistData+n); + nActual = fts3PutVarint(c, nActualData); + assert( nActualData<=nData ); + assert( nActual<=n ); + + /* If the new doclist is big enough for force a standalone leaf + ** node, we can immediately flush it inline without doing the + ** memmove(). + */ + /* TODO(shess) This test matches leafWriterStep(), which does this + ** test before it knows the cost to varint-encode the term and + ** doclist lengths. At some point, change to + ** pWriter->data.nData-iTermData>STANDALONE_MIN. + */ + if( nTerm+nActualData>STANDALONE_MIN ){ + /* Push leaf node from before this term. */ + if( iTermData>0 ){ + rc = leafWriterInternalFlush(v, pWriter, 0, iTermData); + if( rc!=SQLITE_OK ) return rc; + + pWriter->nTermDistinct = nTermDistinct; + } + + /* Fix the encoded doclist length. */ + iDoclistData += n - nActual; + memcpy(pWriter->data.pData+iDoclistData, c, nActual); + + /* Push the standalone leaf node. */ + rc = leafWriterInlineFlush(v, pWriter, pTerm, nTerm, iDoclistData); + if( rc!=SQLITE_OK ) return rc; + + /* Leave the node empty. */ + dataBufferReset(&pWriter->data); + + return rc; + } + + /* At this point, we know that the doclist was small, so do the + ** memmove if indicated. + */ + if( nActualdata.pData+iDoclistData+nActual, + pWriter->data.pData+iDoclistData+n, + pWriter->data.nData-(iDoclistData+n)); + pWriter->data.nData -= n-nActual; + } + + /* Replace written length with actual length. */ + memcpy(pWriter->data.pData+iDoclistData, c, nActual); + + /* If the node is too large, break things up. */ + /* TODO(shess) This test matches leafWriterStep(), which does this + ** test before it knows the cost to varint-encode the term and + ** doclist lengths. At some point, change to + ** pWriter->data.nData>LEAF_MAX. + */ + if( iTermData+nTerm+nActualData>LEAF_MAX ){ + /* Flush out the leading data as a node */ + rc = leafWriterInternalFlush(v, pWriter, 0, iTermData); + if( rc!=SQLITE_OK ) return rc; + + pWriter->nTermDistinct = nTermDistinct; + + /* Rebuild header using the current term */ + n = fts3PutVarint(pWriter->data.pData, 0); + n += fts3PutVarint(pWriter->data.pData+n, nTerm); + memcpy(pWriter->data.pData+n, pTerm, nTerm); + n += nTerm; + + /* There should always be room, because the previous encoding + ** included all data necessary to construct the term. + */ + assert( ndata.nData-iDoclistDatadata.pData+n, + pWriter->data.pData+iDoclistData, + pWriter->data.nData-iDoclistData); + pWriter->data.nData -= iDoclistData-n; + } + ASSERT_VALID_LEAF_NODE(pWriter->data.pData, pWriter->data.nData); + + return SQLITE_OK; +} + +/* Push pTerm[nTerm] along with the doclist data to the leaf layer of +** %_segments. +*/ +/* TODO(shess) Revise writeZeroSegment() so that doclists are +** constructed directly in pWriter->data. +*/ +static int leafWriterStep(fulltext_vtab *v, LeafWriter *pWriter, + const char *pTerm, int nTerm, + const char *pData, int nData){ + int rc; + DLReader reader; + + dlrInit(&reader, DL_DEFAULT, pData, nData); + rc = leafWriterStepMerge(v, pWriter, pTerm, nTerm, &reader, 1); + dlrDestroy(&reader); + + return rc; +} + + +/****************************************************************/ +/* LeafReader is used to iterate over an individual leaf node. */ +typedef struct LeafReader { + DataBuffer term; /* copy of current term. */ + + const char *pData; /* data for current term. */ + int nData; +} LeafReader; + +static void leafReaderDestroy(LeafReader *pReader){ + dataBufferDestroy(&pReader->term); + SCRAMBLE(pReader); +} + +static int leafReaderAtEnd(LeafReader *pReader){ + return pReader->nData<=0; +} + +/* Access the current term. */ +static int leafReaderTermBytes(LeafReader *pReader){ + return pReader->term.nData; +} +static const char *leafReaderTerm(LeafReader *pReader){ + assert( pReader->term.nData>0 ); + return pReader->term.pData; +} + +/* Access the doclist data for the current term. */ +static int leafReaderDataBytes(LeafReader *pReader){ + int nData; + assert( pReader->term.nData>0 ); + fts3GetVarint32(pReader->pData, &nData); + return nData; +} +static const char *leafReaderData(LeafReader *pReader){ + int n, nData; + assert( pReader->term.nData>0 ); + n = fts3GetVarint32(pReader->pData, &nData); + return pReader->pData+n; +} + +static void leafReaderInit(const char *pData, int nData, + LeafReader *pReader){ + int nTerm, n; + + assert( nData>0 ); + assert( pData[0]=='\0' ); + + CLEAR(pReader); + + /* Read the first term, skipping the header byte. */ + n = fts3GetVarint32(pData+1, &nTerm); + dataBufferInit(&pReader->term, nTerm); + dataBufferReplace(&pReader->term, pData+1+n, nTerm); + + /* Position after the first term. */ + assert( 1+n+nTermpData = pData+1+n+nTerm; + pReader->nData = nData-1-n-nTerm; +} + +/* Step the reader forward to the next term. */ +static void leafReaderStep(LeafReader *pReader){ + int n, nData, nPrefix, nSuffix; + assert( !leafReaderAtEnd(pReader) ); + + /* Skip previous entry's data block. */ + n = fts3GetVarint32(pReader->pData, &nData); + assert( n+nData<=pReader->nData ); + pReader->pData += n+nData; + pReader->nData -= n+nData; + + if( !leafReaderAtEnd(pReader) ){ + /* Construct the new term using a prefix from the old term plus a + ** suffix from the leaf data. + */ + n = fts3GetVarint32(pReader->pData, &nPrefix); + n += fts3GetVarint32(pReader->pData+n, &nSuffix); + assert( n+nSuffixnData ); + pReader->term.nData = nPrefix; + dataBufferAppend(&pReader->term, pReader->pData+n, nSuffix); + + pReader->pData += n+nSuffix; + pReader->nData -= n+nSuffix; + } +} + +/* strcmp-style comparison of pReader's current term against pTerm. +** If isPrefix, equality means equal through nTerm bytes. +*/ +static int leafReaderTermCmp(LeafReader *pReader, + const char *pTerm, int nTerm, int isPrefix){ + int c, n = pReader->term.nDataterm.nData : nTerm; + if( n==0 ){ + if( pReader->term.nData>0 ) return -1; + if(nTerm>0 ) return 1; + return 0; + } + + c = memcmp(pReader->term.pData, pTerm, n); + if( c!=0 ) return c; + if( isPrefix && n==nTerm ) return 0; + return pReader->term.nData - nTerm; +} + + +/****************************************************************/ +/* LeavesReader wraps LeafReader to allow iterating over the entire +** leaf layer of the tree. +*/ +typedef struct LeavesReader { + int idx; /* Index within the segment. */ + + sqlite3_stmt *pStmt; /* Statement we're streaming leaves from. */ + int eof; /* we've seen SQLITE_DONE from pStmt. */ + + LeafReader leafReader; /* reader for the current leaf. */ + DataBuffer rootData; /* root data for inline. */ +} LeavesReader; + +/* Access the current term. */ +static int leavesReaderTermBytes(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderTermBytes(&pReader->leafReader); +} +static const char *leavesReaderTerm(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderTerm(&pReader->leafReader); +} + +/* Access the doclist data for the current term. */ +static int leavesReaderDataBytes(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderDataBytes(&pReader->leafReader); +} +static const char *leavesReaderData(LeavesReader *pReader){ + assert( !pReader->eof ); + return leafReaderData(&pReader->leafReader); +} + +static int leavesReaderAtEnd(LeavesReader *pReader){ + return pReader->eof; +} + +/* loadSegmentLeaves() may not read all the way to SQLITE_DONE, thus +** leaving the statement handle open, which locks the table. +*/ +/* TODO(shess) This "solution" is not satisfactory. Really, there +** should be check-in function for all statement handles which +** arranges to call sqlite3_reset(). This most likely will require +** modification to control flow all over the place, though, so for now +** just punt. +** +** Note the the current system assumes that segment merges will run to +** completion, which is why this particular probably hasn't arisen in +** this case. Probably a brittle assumption. +*/ +static int leavesReaderReset(LeavesReader *pReader){ + return sqlite3_reset(pReader->pStmt); +} + +static void leavesReaderDestroy(LeavesReader *pReader){ + leafReaderDestroy(&pReader->leafReader); + dataBufferDestroy(&pReader->rootData); + SCRAMBLE(pReader); +} + +/* Initialize pReader with the given root data (if iStartBlockid==0 +** the leaf data was entirely contained in the root), or from the +** stream of blocks between iStartBlockid and iEndBlockid, inclusive. +*/ +static int leavesReaderInit(fulltext_vtab *v, + int idx, + sqlite_int64 iStartBlockid, + sqlite_int64 iEndBlockid, + const char *pRootData, int nRootData, + LeavesReader *pReader){ + CLEAR(pReader); + pReader->idx = idx; + + dataBufferInit(&pReader->rootData, 0); + if( iStartBlockid==0 ){ + /* Entire leaf level fit in root data. */ + dataBufferReplace(&pReader->rootData, pRootData, nRootData); + leafReaderInit(pReader->rootData.pData, pReader->rootData.nData, + &pReader->leafReader); + }else{ + sqlite3_stmt *s; + int rc = sql_get_leaf_statement(v, idx, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iStartBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 2, iEndBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ){ + pReader->eof = 1; + return SQLITE_OK; + } + if( rc!=SQLITE_ROW ) return rc; + + pReader->pStmt = s; + leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), + sqlite3_column_bytes(pReader->pStmt, 0), + &pReader->leafReader); + } + return SQLITE_OK; +} + +/* Step the current leaf forward to the next term. If we reach the +** end of the current leaf, step forward to the next leaf block. +*/ +static int leavesReaderStep(fulltext_vtab *v, LeavesReader *pReader){ + assert( !leavesReaderAtEnd(pReader) ); + leafReaderStep(&pReader->leafReader); + + if( leafReaderAtEnd(&pReader->leafReader) ){ + int rc; + if( pReader->rootData.pData ){ + pReader->eof = 1; + return SQLITE_OK; + } + rc = sqlite3_step(pReader->pStmt); + if( rc!=SQLITE_ROW ){ + pReader->eof = 1; + return rc==SQLITE_DONE ? SQLITE_OK : rc; + } + leafReaderDestroy(&pReader->leafReader); + leafReaderInit(sqlite3_column_blob(pReader->pStmt, 0), + sqlite3_column_bytes(pReader->pStmt, 0), + &pReader->leafReader); + } + return SQLITE_OK; +} + +/* Order LeavesReaders by their term, ignoring idx. Readers at eof +** always sort to the end. +*/ +static int leavesReaderTermCmp(LeavesReader *lr1, LeavesReader *lr2){ + if( leavesReaderAtEnd(lr1) ){ + if( leavesReaderAtEnd(lr2) ) return 0; + return 1; + } + if( leavesReaderAtEnd(lr2) ) return -1; + + return leafReaderTermCmp(&lr1->leafReader, + leavesReaderTerm(lr2), leavesReaderTermBytes(lr2), + 0); +} + +/* Similar to leavesReaderTermCmp(), with additional ordering by idx +** so that older segments sort before newer segments. +*/ +static int leavesReaderCmp(LeavesReader *lr1, LeavesReader *lr2){ + int c = leavesReaderTermCmp(lr1, lr2); + if( c!=0 ) return c; + return lr1->idx-lr2->idx; +} + +/* Assume that pLr[1]..pLr[nLr] are sorted. Bubble pLr[0] into its +** sorted position. +*/ +static void leavesReaderReorder(LeavesReader *pLr, int nLr){ + while( nLr>1 && leavesReaderCmp(pLr, pLr+1)>0 ){ + LeavesReader tmp = pLr[0]; + pLr[0] = pLr[1]; + pLr[1] = tmp; + nLr--; + pLr++; + } +} + +/* Initializes pReaders with the segments from level iLevel, returning +** the number of segments in *piReaders. Leaves pReaders in sorted +** order. +*/ +static int leavesReadersInit(fulltext_vtab *v, int iLevel, + LeavesReader *pReaders, int *piReaders){ + sqlite3_stmt *s; + int i, rc = sql_get_statement(v, SEGDIR_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int(s, 1, iLevel); + if( rc!=SQLITE_OK ) return rc; + + i = 0; + while( (rc = sqlite3_step(s))==SQLITE_ROW ){ + sqlite_int64 iStart = sqlite3_column_int64(s, 0); + sqlite_int64 iEnd = sqlite3_column_int64(s, 1); + const char *pRootData = sqlite3_column_blob(s, 2); + int nRootData = sqlite3_column_bytes(s, 2); + + assert( i0 ){ + leavesReaderDestroy(&pReaders[i]); + } + return rc; + } + + *piReaders = i; + + /* Leave our results sorted by term, then age. */ + while( i-- ){ + leavesReaderReorder(pReaders+i, *piReaders-i); + } + return SQLITE_OK; +} + +/* Merge doclists from pReaders[nReaders] into a single doclist, which +** is written to pWriter. Assumes pReaders is ordered oldest to +** newest. +*/ +/* TODO(shess) Consider putting this inline in segmentMerge(). */ +static int leavesReadersMerge(fulltext_vtab *v, + LeavesReader *pReaders, int nReaders, + LeafWriter *pWriter){ + DLReader dlReaders[MERGE_COUNT]; + const char *pTerm = leavesReaderTerm(pReaders); + int i, nTerm = leavesReaderTermBytes(pReaders); + + assert( nReaders<=MERGE_COUNT ); + + for(i=0; i0 ){ + rc = leavesReaderStep(v, lrs+i); + if( rc!=SQLITE_OK ) goto err; + + /* Reorder by term, then by age. */ + leavesReaderReorder(lrs+i, MERGE_COUNT-i); + } + } + + for(i=0; i0 ); + + for(rc=SQLITE_OK; rc==SQLITE_OK && !leavesReaderAtEnd(pReader); + rc=leavesReaderStep(v, pReader)){ + /* TODO(shess) Really want leavesReaderTermCmp(), but that name is + ** already taken to compare the terms of two LeavesReaders. Think + ** on a better name. [Meanwhile, break encapsulation rather than + ** use a confusing name.] + */ + int c = leafReaderTermCmp(&pReader->leafReader, pTerm, nTerm, isPrefix); + if( c>0 ) break; /* Past any possible matches. */ + if( c==0 ){ + const char *pData = leavesReaderData(pReader); + int iBuffer, nData = leavesReaderDataBytes(pReader); + + /* Find the first empty buffer. */ + for(iBuffer=0; iBuffer0 ){ + assert(pBuffers!=NULL); + memcpy(p, pBuffers, nBuffers*sizeof(*pBuffers)); + sqlite3_free(pBuffers); + } + pBuffers = p; + } + dataBufferInit(&(pBuffers[nBuffers]), 0); + nBuffers++; + } + + /* At this point, must have an empty at iBuffer. */ + assert(iBufferpData, p->nData); + + /* dataBufferReset() could allow a large doclist to blow up + ** our memory requirements. + */ + if( p->nCapacity<1024 ){ + dataBufferReset(p); + }else{ + dataBufferDestroy(p); + dataBufferInit(p, 0); + } + } + } + } + } + + /* Union all the doclists together into *out. */ + /* TODO(shess) What if *out is big? Sigh. */ + if( rc==SQLITE_OK && nBuffers>0 ){ + int iBuffer; + for(iBuffer=0; iBuffer0 ){ + if( out->nData==0 ){ + dataBufferSwap(out, &(pBuffers[iBuffer])); + }else{ + docListAccumulateUnion(out, pBuffers[iBuffer].pData, + pBuffers[iBuffer].nData); + } + } + } + } + + while( nBuffers-- ){ + dataBufferDestroy(&(pBuffers[nBuffers])); + } + if( pBuffers!=NULL ) sqlite3_free(pBuffers); + + return rc; +} + +/* Call loadSegmentLeavesInt() with pData/nData as input. */ +static int loadSegmentLeaf(fulltext_vtab *v, const char *pData, int nData, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + LeavesReader reader; + int rc; + + assert( nData>1 ); + assert( *pData=='\0' ); + rc = leavesReaderInit(v, 0, 0, 0, pData, nData, &reader); + if( rc!=SQLITE_OK ) return rc; + + rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out); + leavesReaderReset(&reader); + leavesReaderDestroy(&reader); + return rc; +} + +/* Call loadSegmentLeavesInt() with the leaf nodes from iStartLeaf to +** iEndLeaf (inclusive) as input, and merge the resulting doclist into +** out. +*/ +static int loadSegmentLeaves(fulltext_vtab *v, + sqlite_int64 iStartLeaf, sqlite_int64 iEndLeaf, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + int rc; + LeavesReader reader; + + assert( iStartLeaf<=iEndLeaf ); + rc = leavesReaderInit(v, 0, iStartLeaf, iEndLeaf, NULL, 0, &reader); + if( rc!=SQLITE_OK ) return rc; + + rc = loadSegmentLeavesInt(v, &reader, pTerm, nTerm, isPrefix, out); + leavesReaderReset(&reader); + leavesReaderDestroy(&reader); + return rc; +} + +/* Taking pData/nData as an interior node, find the sequence of child +** nodes which could include pTerm/nTerm/isPrefix. Note that the +** interior node terms logically come between the blocks, so there is +** one more blockid than there are terms (that block contains terms >= +** the last interior-node term). +*/ +/* TODO(shess) The calling code may already know that the end child is +** not worth calculating, because the end may be in a later sibling +** node. Consider whether breaking symmetry is worthwhile. I suspect +** it is not worthwhile. +*/ +static void getChildrenContaining(const char *pData, int nData, + const char *pTerm, int nTerm, int isPrefix, + sqlite_int64 *piStartChild, + sqlite_int64 *piEndChild){ + InteriorReader reader; + + assert( nData>1 ); + assert( *pData!='\0' ); + interiorReaderInit(pData, nData, &reader); + + /* Scan for the first child which could contain pTerm/nTerm. */ + while( !interiorReaderAtEnd(&reader) ){ + if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break; + interiorReaderStep(&reader); + } + *piStartChild = interiorReaderCurrentBlockid(&reader); + + /* Keep scanning to find a term greater than our term, using prefix + ** comparison if indicated. If isPrefix is false, this will be the + ** same blockid as the starting block. + */ + while( !interiorReaderAtEnd(&reader) ){ + if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break; + interiorReaderStep(&reader); + } + *piEndChild = interiorReaderCurrentBlockid(&reader); + + interiorReaderDestroy(&reader); + + /* Children must ascend, and if !prefix, both must be the same. */ + assert( *piEndChild>=*piStartChild ); + assert( isPrefix || *piStartChild==*piEndChild ); +} + +/* Read block at iBlockid and pass it with other params to +** getChildrenContaining(). +*/ +static int loadAndGetChildrenContaining( + fulltext_vtab *v, + sqlite_int64 iBlockid, + const char *pTerm, int nTerm, int isPrefix, + sqlite_int64 *piStartChild, sqlite_int64 *piEndChild +){ + sqlite3_stmt *s = NULL; + int rc; + + assert( iBlockid!=0 ); + assert( pTerm!=NULL ); + assert( nTerm!=0 ); /* TODO(shess) Why not allow this? */ + assert( piStartChild!=NULL ); + assert( piEndChild!=NULL ); + + rc = sql_get_statement(v, BLOCK_SELECT_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_bind_int64(s, 1, iBlockid); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3_step(s); + if( rc==SQLITE_DONE ) return SQLITE_ERROR; + if( rc!=SQLITE_ROW ) return rc; + + getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0), + pTerm, nTerm, isPrefix, piStartChild, piEndChild); + + /* We expect only one row. We must execute another sqlite3_step() + * to complete the iteration; otherwise the table will remain + * locked. */ + rc = sqlite3_step(s); + if( rc==SQLITE_ROW ) return SQLITE_ERROR; + if( rc!=SQLITE_DONE ) return rc; + + return SQLITE_OK; +} + +/* Traverse the tree represented by pData[nData] looking for +** pTerm[nTerm], placing its doclist into *out. This is internal to +** loadSegment() to make error-handling cleaner. +*/ +static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData, + sqlite_int64 iLeavesEnd, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + /* Special case where root is a leaf. */ + if( *pData=='\0' ){ + return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out); + }else{ + int rc; + sqlite_int64 iStartChild, iEndChild; + + /* Process pData as an interior node, then loop down the tree + ** until we find the set of leaf nodes to scan for the term. + */ + getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix, + &iStartChild, &iEndChild); + while( iStartChild>iLeavesEnd ){ + sqlite_int64 iNextStart, iNextEnd; + rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix, + &iNextStart, &iNextEnd); + if( rc!=SQLITE_OK ) return rc; + + /* If we've branched, follow the end branch, too. */ + if( iStartChild!=iEndChild ){ + sqlite_int64 iDummy; + rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix, + &iDummy, &iNextEnd); + if( rc!=SQLITE_OK ) return rc; + } + + assert( iNextStart<=iNextEnd ); + iStartChild = iNextStart; + iEndChild = iNextEnd; + } + assert( iStartChild<=iLeavesEnd ); + assert( iEndChild<=iLeavesEnd ); + + /* Scan through the leaf segments for doclists. */ + return loadSegmentLeaves(v, iStartChild, iEndChild, + pTerm, nTerm, isPrefix, out); + } +} + +/* Call loadSegmentInt() to collect the doclist for pTerm/nTerm, then +** merge its doclist over *out (any duplicate doclists read from the +** segment rooted at pData will overwrite those in *out). +*/ +/* TODO(shess) Consider changing this to determine the depth of the +** leaves using either the first characters of interior nodes (when +** ==1, we're one level above the leaves), or the first character of +** the root (which will describe the height of the tree directly). +** Either feels somewhat tricky to me. +*/ +/* TODO(shess) The current merge is likely to be slow for large +** doclists (though it should process from newest/smallest to +** oldest/largest, so it may not be that bad). It might be useful to +** modify things to allow for N-way merging. This could either be +** within a segment, with pairwise merges across segments, or across +** all segments at once. +*/ +static int loadSegment(fulltext_vtab *v, const char *pData, int nData, + sqlite_int64 iLeavesEnd, + const char *pTerm, int nTerm, int isPrefix, + DataBuffer *out){ + DataBuffer result; + int rc; + + assert( nData>1 ); + + /* This code should never be called with buffered updates. */ + assert( v->nPendingData<0 ); + + dataBufferInit(&result, 0); + rc = loadSegmentInt(v, pData, nData, iLeavesEnd, + pTerm, nTerm, isPrefix, &result); + if( rc==SQLITE_OK && result.nData>0 ){ + if( out->nData==0 ){ + DataBuffer tmp = *out; + *out = result; + result = tmp; + }else{ + DataBuffer merged; + DLReader readers[2]; + + dlrInit(&readers[0], DL_DEFAULT, out->pData, out->nData); + dlrInit(&readers[1], DL_DEFAULT, result.pData, result.nData); + dataBufferInit(&merged, out->nData+result.nData); + docListMerge(&merged, readers, 2); + dataBufferDestroy(out); + *out = merged; + dlrDestroy(&readers[0]); + dlrDestroy(&readers[1]); + } + } + dataBufferDestroy(&result); + return rc; +} + +/* Scan the database and merge together the posting lists for the term +** into *out. +*/ +static int termSelect(fulltext_vtab *v, int iColumn, + const char *pTerm, int nTerm, int isPrefix, + DocListType iType, DataBuffer *out){ + DataBuffer doclist; + sqlite3_stmt *s; + int rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s); + if( rc!=SQLITE_OK ) return rc; + + /* This code should never be called with buffered updates. */ + assert( v->nPendingData<0 ); + + dataBufferInit(&doclist, 0); + + /* Traverse the segments from oldest to newest so that newer doclist + ** elements for given docids overwrite older elements. + */ + while( (rc = sqlite3_step(s))==SQLITE_ROW ){ + const char *pData = sqlite3_column_blob(s, 0); + const int nData = sqlite3_column_bytes(s, 0); + const sqlite_int64 iLeavesEnd = sqlite3_column_int64(s, 1); + rc = loadSegment(v, pData, nData, iLeavesEnd, pTerm, nTerm, isPrefix, + &doclist); + if( rc!=SQLITE_OK ) goto err; + } + if( rc==SQLITE_DONE ){ + if( doclist.nData!=0 ){ + /* TODO(shess) The old term_select_all() code applied the column + ** restrict as we merged segments, leading to smaller buffers. + ** This is probably worthwhile to bring back, once the new storage + ** system is checked in. + */ + if( iColumn==v->nColumn) iColumn = -1; + docListTrim(DL_DEFAULT, doclist.pData, doclist.nData, + iColumn, iType, out); + } + rc = SQLITE_OK; + } + + err: + dataBufferDestroy(&doclist); + return rc; +} + +/****************************************************************/ +/* Used to hold hashtable data for sorting. */ +typedef struct TermData { + const char *pTerm; + int nTerm; + DLCollector *pCollector; +} TermData; + +/* Orders TermData elements in strcmp fashion ( <0 for less-than, 0 +** for equal, >0 for greater-than). +*/ +static int termDataCmp(const void *av, const void *bv){ + const TermData *a = (const TermData *)av; + const TermData *b = (const TermData *)bv; + int n = a->nTermnTerm ? a->nTerm : b->nTerm; + int c = memcmp(a->pTerm, b->pTerm, n); + if( c!=0 ) return c; + return a->nTerm-b->nTerm; +} + +/* Order pTerms data by term, then write a new level 0 segment using +** LeafWriter. +*/ +static int writeZeroSegment(fulltext_vtab *v, fts3Hash *pTerms){ + fts3HashElem *e; + int idx, rc, i, n; + TermData *pData; + LeafWriter writer; + DataBuffer dl; + + /* Determine the next index at level 0, merging as necessary. */ + rc = segdirNextIndex(v, 0, &idx); + if( rc!=SQLITE_OK ) return rc; + + n = fts3HashCount(pTerms); + pData = sqlite3_malloc(n*sizeof(TermData)); + + for(i = 0, e = fts3HashFirst(pTerms); e; i++, e = fts3HashNext(e)){ + assert( i1 ) qsort(pData, n, sizeof(*pData), termDataCmp); + + /* TODO(shess) Refactor so that we can write directly to the segment + ** DataBuffer, as happens for segment merges. + */ + leafWriterInit(0, idx, &writer); + dataBufferInit(&dl, 0); + for(i=0; inPendingData>=0 ){ + fts3HashElem *e; + for(e=fts3HashFirst(&v->pendingTerms); e; e=fts3HashNext(e)){ + dlcDelete(fts3HashData(e)); + } + fts3HashClear(&v->pendingTerms); + v->nPendingData = -1; + } + return SQLITE_OK; +} + +/* If pendingTerms has data, flush it to a level-zero segment, and +** free it. +*/ +static int flushPendingTerms(fulltext_vtab *v){ + if( v->nPendingData>=0 ){ + int rc = writeZeroSegment(v, &v->pendingTerms); + if( rc==SQLITE_OK ) clearPendingTerms(v); + return rc; + } + return SQLITE_OK; +} + +/* If pendingTerms is "too big", or docid is out of order, flush it. +** Regardless, be certain that pendingTerms is initialized for use. +*/ +static int initPendingTerms(fulltext_vtab *v, sqlite_int64 iDocid){ + /* TODO(shess) Explore whether partially flushing the buffer on + ** forced-flush would provide better performance. I suspect that if + ** we ordered the doclists by size and flushed the largest until the + ** buffer was half empty, that would let the less frequent terms + ** generate longer doclists. + */ + if( iDocid<=v->iPrevDocid || v->nPendingData>kPendingThreshold ){ + int rc = flushPendingTerms(v); + if( rc!=SQLITE_OK ) return rc; + } + if( v->nPendingData<0 ){ + fts3HashInit(&v->pendingTerms, FTS3_HASH_STRING, 1); + v->nPendingData = 0; + } + v->iPrevDocid = iDocid; + return SQLITE_OK; +} + +/* This function implements the xUpdate callback; it is the top-level entry + * point for inserting, deleting or updating a row in a full-text table. */ +static int fulltextUpdate(sqlite3_vtab *pVtab, int nArg, sqlite3_value **ppArg, + sqlite_int64 *pRowid){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + int rc; + + FTSTRACE(("FTS3 Update %p\n", pVtab)); + + if( nArg<2 ){ + rc = index_delete(v, sqlite3_value_int64(ppArg[0])); + } else if( sqlite3_value_type(ppArg[0]) != SQLITE_NULL ){ + /* An update: + * ppArg[0] = old rowid + * ppArg[1] = new rowid + * ppArg[2..2+v->nColumn-1] = values + * ppArg[2+v->nColumn] = value for magic column (we ignore this) + * ppArg[2+v->nColumn+1] = value for docid + */ + sqlite_int64 rowid = sqlite3_value_int64(ppArg[0]); + if( sqlite3_value_type(ppArg[1]) != SQLITE_INTEGER || + sqlite3_value_int64(ppArg[1]) != rowid ){ + rc = SQLITE_ERROR; /* we don't allow changing the rowid */ + }else if( sqlite3_value_type(ppArg[2+v->nColumn+1]) != SQLITE_INTEGER || + sqlite3_value_int64(ppArg[2+v->nColumn+1]) != rowid ){ + rc = SQLITE_ERROR; /* we don't allow changing the docid */ + }else{ + assert( nArg==2+v->nColumn+2); + rc = index_update(v, rowid, &ppArg[2]); + } + } else { + /* An insert: + * ppArg[1] = requested rowid + * ppArg[2..2+v->nColumn-1] = values + * ppArg[2+v->nColumn] = value for magic column (we ignore this) + * ppArg[2+v->nColumn+1] = value for docid + */ + sqlite3_value *pRequestDocid = ppArg[2+v->nColumn+1]; + assert( nArg==2+v->nColumn+2); + if( SQLITE_NULL != sqlite3_value_type(pRequestDocid) && + SQLITE_NULL != sqlite3_value_type(ppArg[1]) ){ + /* TODO(shess) Consider allowing this to work if the values are + ** identical. I'm inclined to discourage that usage, though, + ** given that both rowid and docid are special columns. Better + ** would be to define one or the other as the default winner, + ** but should it be fts3-centric (docid) or SQLite-centric + ** (rowid)? + */ + rc = SQLITE_ERROR; + }else{ + if( SQLITE_NULL == sqlite3_value_type(pRequestDocid) ){ + pRequestDocid = ppArg[1]; + } + rc = index_insert(v, pRequestDocid, &ppArg[2], pRowid); + } + } + + return rc; +} + +static int fulltextSync(sqlite3_vtab *pVtab){ + FTSTRACE(("FTS3 xSync()\n")); + return flushPendingTerms((fulltext_vtab *)pVtab); +} + +static int fulltextBegin(sqlite3_vtab *pVtab){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + FTSTRACE(("FTS3 xBegin()\n")); + + /* Any buffered updates should have been cleared by the previous + ** transaction. + */ + assert( v->nPendingData<0 ); + return clearPendingTerms(v); +} + +static int fulltextCommit(sqlite3_vtab *pVtab){ + fulltext_vtab *v = (fulltext_vtab *) pVtab; + FTSTRACE(("FTS3 xCommit()\n")); + + /* Buffered updates should have been cleared by fulltextSync(). */ + assert( v->nPendingData<0 ); + return clearPendingTerms(v); +} + +static int fulltextRollback(sqlite3_vtab *pVtab){ + FTSTRACE(("FTS3 xRollback()\n")); + return clearPendingTerms((fulltext_vtab *)pVtab); +} + +/* +** Implementation of the snippet() function for FTS3 +*/ +static void snippetFunc( + sqlite3_context *pContext, + int argc, + sqlite3_value **argv +){ + fulltext_cursor *pCursor; + if( argc<1 ) return; + if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || + sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ + sqlite3_result_error(pContext, "illegal first argument to html_snippet",-1); + }else{ + const char *zStart = ""; + const char *zEnd = ""; + const char *zEllipsis = "..."; + memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); + if( argc>=2 ){ + zStart = (const char*)sqlite3_value_text(argv[1]); + if( argc>=3 ){ + zEnd = (const char*)sqlite3_value_text(argv[2]); + if( argc>=4 ){ + zEllipsis = (const char*)sqlite3_value_text(argv[3]); + } + } + } + snippetAllOffsets(pCursor); + snippetText(pCursor, zStart, zEnd, zEllipsis); + sqlite3_result_text(pContext, pCursor->snippet.zSnippet, + pCursor->snippet.nSnippet, SQLITE_STATIC); + } +} + +/* +** Implementation of the offsets() function for FTS3 +*/ +static void snippetOffsetsFunc( + sqlite3_context *pContext, + int argc, + sqlite3_value **argv +){ + fulltext_cursor *pCursor; + if( argc<1 ) return; + if( sqlite3_value_type(argv[0])!=SQLITE_BLOB || + sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){ + sqlite3_result_error(pContext, "illegal first argument to offsets",-1); + }else{ + memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor)); + snippetAllOffsets(pCursor); + snippetOffsetText(&pCursor->snippet); + sqlite3_result_text(pContext, + pCursor->snippet.zOffset, pCursor->snippet.nOffset, + SQLITE_STATIC); + } +} + +/* +** This routine implements the xFindFunction method for the FTS3 +** virtual table. +*/ +static int fulltextFindFunction( + sqlite3_vtab *pVtab, + int nArg, + const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg +){ + if( strcmp(zName,"snippet")==0 ){ + *pxFunc = snippetFunc; + return 1; + }else if( strcmp(zName,"offsets")==0 ){ + *pxFunc = snippetOffsetsFunc; + return 1; + } + return 0; +} + +/* +** Rename an fts3 table. +*/ +static int fulltextRename( + sqlite3_vtab *pVtab, + const char *zName +){ + fulltext_vtab *p = (fulltext_vtab *)pVtab; + int rc = SQLITE_NOMEM; + char *zSql = sqlite3_mprintf( + "ALTER TABLE %Q.'%q_content' RENAME TO '%q_content';" + "ALTER TABLE %Q.'%q_segments' RENAME TO '%q_segments';" + "ALTER TABLE %Q.'%q_segdir' RENAME TO '%q_segdir';" + , p->zDb, p->zName, zName + , p->zDb, p->zName, zName + , p->zDb, p->zName, zName + ); + if( zSql ){ + rc = sqlite3_exec(p->db, zSql, 0, 0, 0); + sqlite3_free(zSql); + } + return rc; +} + +static const sqlite3_module fts3Module = { + /* iVersion */ 0, + /* xCreate */ fulltextCreate, + /* xConnect */ fulltextConnect, + /* xBestIndex */ fulltextBestIndex, + /* xDisconnect */ fulltextDisconnect, + /* xDestroy */ fulltextDestroy, + /* xOpen */ fulltextOpen, + /* xClose */ fulltextClose, + /* xFilter */ fulltextFilter, + /* xNext */ fulltextNext, + /* xEof */ fulltextEof, + /* xColumn */ fulltextColumn, + /* xRowid */ fulltextRowid, + /* xUpdate */ fulltextUpdate, + /* xBegin */ fulltextBegin, + /* xSync */ fulltextSync, + /* xCommit */ fulltextCommit, + /* xRollback */ fulltextRollback, + /* xFindFunction */ fulltextFindFunction, + /* xRename */ fulltextRename, +}; + +static void hashDestroy(void *p){ + fts3Hash *pHash = (fts3Hash *)p; + sqlite3Fts3HashClear(pHash); + sqlite3_free(pHash); +} + +/* +** The fts3 built-in tokenizers - "simple" and "porter" - are implemented +** in files fts3_tokenizer1.c and fts3_porter.c respectively. The following +** two forward declarations are for functions declared in these files +** used to retrieve the respective implementations. +** +** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed +** to by the argument to point a the "simple" tokenizer implementation. +** Function ...PorterTokenizerModule() sets *pModule to point to the +** porter tokenizer/stemmer implementation. +*/ +void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); +void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); +void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); + +int sqlite3Fts3InitHashTable(sqlite3 *, fts3Hash *, const char *); + +/* +** Initialise the fts3 extension. If this extension is built as part +** of the sqlite library, then this function is called directly by +** SQLite. If fts3 is built as a dynamically loadable extension, this +** function is called by the sqlite3_extension_init() entry point. +*/ +int sqlite3Fts3Init(sqlite3 *db){ + int rc = SQLITE_OK; + fts3Hash *pHash = 0; + const sqlite3_tokenizer_module *pSimple = 0; + const sqlite3_tokenizer_module *pPorter = 0; + const sqlite3_tokenizer_module *pIcu = 0; + + sqlite3Fts3SimpleTokenizerModule(&pSimple); + sqlite3Fts3PorterTokenizerModule(&pPorter); +#ifdef SQLITE_ENABLE_ICU + sqlite3Fts3IcuTokenizerModule(&pIcu); +#endif + + /* Allocate and initialise the hash-table used to store tokenizers. */ + pHash = sqlite3_malloc(sizeof(fts3Hash)); + if( !pHash ){ + rc = SQLITE_NOMEM; + }else{ + sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); + } + + /* Load the built-in tokenizers into the hash table */ + if( rc==SQLITE_OK ){ + if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) + || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) + || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) + ){ + rc = SQLITE_NOMEM; + } + } + + /* Create the virtual table wrapper around the hash-table and overload + ** the two scalar functions. If this is successful, register the + ** module with sqlite. + */ + if( SQLITE_OK==rc + && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) + && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) + && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1)) + ){ + return sqlite3_create_module_v2( + db, "fts3", &fts3Module, (void *)pHash, hashDestroy + ); + } + + /* An error has occured. Delete the hash table and return the error code. */ + assert( rc!=SQLITE_OK ); + if( pHash ){ + sqlite3Fts3HashClear(pHash); + sqlite3_free(pHash); + } + return rc; +} + +#if !SQLITE_CORE +int sqlite3_extension_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi) + return sqlite3Fts3Init(db); +} +#endif + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.h new file mode 100644 index 0000000..c1aa8ca --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3.h @@ -0,0 +1,26 @@ +/* +** 2006 Oct 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. +** +****************************************************************************** +** +** This header file is used by programs that want to link against the +** FTS3 library. All it does is declare the sqlite3Fts3Init() interface. +*/ +#include "sqlite3.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int sqlite3Fts3Init(sqlite3 *db); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.c new file mode 100644 index 0000000..64bd5d0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.c @@ -0,0 +1,374 @@ +/* +** 2001 September 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 is the implementation of generic hash-tables used in SQLite. +** We've modified it slightly to serve as a standalone hash table +** implementation for the full-text indexing module. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS3 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS3 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) + +#include +#include +#include + +#include "sqlite3.h" +#include "fts3_hash.h" + +/* +** Malloc and Free functions +*/ +static void *fts3HashMalloc(int n){ + void *p = sqlite3_malloc(n); + if( p ){ + memset(p, 0, n); + } + return p; +} +static void fts3HashFree(void *p){ + sqlite3_free(p); +} + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +** keyClass is one of the constants +** FTS3_HASH_BINARY or FTS3_HASH_STRING. The value of keyClass +** determines what kind of key the hash table will use. "copyKey" is +** true if the hash table should make its own private copy of keys and +** false if it should just use the supplied pointer. +*/ +void sqlite3Fts3HashInit(fts3Hash *pNew, int keyClass, int copyKey){ + assert( pNew!=0 ); + assert( keyClass>=FTS3_HASH_STRING && keyClass<=FTS3_HASH_BINARY ); + pNew->keyClass = keyClass; + pNew->copyKey = copyKey; + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +void sqlite3Fts3HashClear(fts3Hash *pH){ + fts3HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + fts3HashFree(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + fts3HashElem *next_elem = elem->next; + if( pH->copyKey && elem->pKey ){ + fts3HashFree(elem->pKey); + } + fts3HashFree(elem); + elem = next_elem; + } + pH->count = 0; +} + +/* +** Hash and comparison functions when the mode is FTS3_HASH_STRING +*/ +static int fts3StrHash(const void *pKey, int nKey){ + const char *z = (const char *)pKey; + int h = 0; + if( nKey<=0 ) nKey = (int) strlen(z); + while( nKey > 0 ){ + h = (h<<3) ^ h ^ *z++; + nKey--; + } + return h & 0x7fffffff; +} +static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return strncmp((const char*)pKey1,(const char*)pKey2,n1); +} + +/* +** Hash and comparison functions when the mode is FTS3_HASH_BINARY +*/ +static int fts3BinHash(const void *pKey, int nKey){ + int h = 0; + const char *z = (const char *)pKey; + while( nKey-- > 0 ){ + h = (h<<3) ^ h ^ *(z++); + } + return h & 0x7fffffff; +} +static int fts3BinCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return memcmp(pKey1,pKey2,n1); +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** The C syntax in this function definition may be unfamilar to some +** programmers, so we provide the following additional explanation: +** +** The name of the function is "ftsHashFunction". The function takes a +** single parameter "keyClass". The return value of ftsHashFunction() +** is a pointer to another function. Specifically, the return value +** of ftsHashFunction() is a pointer to a function that takes two parameters +** with types "const void*" and "int" and returns an "int". +*/ +static int (*ftsHashFunction(int keyClass))(const void*,int){ + if( keyClass==FTS3_HASH_STRING ){ + return &fts3StrHash; + }else{ + assert( keyClass==FTS3_HASH_BINARY ); + return &fts3BinHash; + } +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** For help in interpreted the obscure C code in the function definition, +** see the header comment on the previous function. +*/ +static int (*ftsCompareFunction(int keyClass))(const void*,int,const void*,int){ + if( keyClass==FTS3_HASH_STRING ){ + return &fts3StrCompare; + }else{ + assert( keyClass==FTS3_HASH_BINARY ); + return &fts3BinCompare; + } +} + +/* Link an element into the hash table +*/ +static void fts3HashInsertElement( + fts3Hash *pH, /* The complete hash table */ + struct _fts3ht *pEntry, /* The entry into which pNew is inserted */ + fts3HashElem *pNew /* The element to be inserted */ +){ + fts3HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** "new_size" must be a power of 2. The hash table might fail +** to resize if sqliteMalloc() fails. +*/ +static void fts3Rehash(fts3Hash *pH, int new_size){ + struct _fts3ht *new_ht; /* The new hash table */ + fts3HashElem *elem, *next_elem; /* For looping over existing elements */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( (new_size & (new_size-1))==0 ); + new_ht = (struct _fts3ht *)fts3HashMalloc( new_size*sizeof(struct _fts3ht) ); + if( new_ht==0 ) return; + fts3HashFree(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size; + xHash = ftsHashFunction(pH->keyClass); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + next_elem = elem->next; + fts3HashInsertElement(pH, &new_ht[h], elem); + } +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. +*/ +static fts3HashElem *fts3FindElementByHash( + const fts3Hash *pH, /* The pH to be searched */ + const void *pKey, /* The key we are searching for */ + int nKey, + int h /* The hash for this key. */ +){ + fts3HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + int (*xCompare)(const void*,int,const void*,int); /* comparison function */ + + if( pH->ht ){ + struct _fts3ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + xCompare = ftsCompareFunction(pH->keyClass); + while( count-- && elem ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void fts3RemoveElementByHash( + fts3Hash *pH, /* The pH containing "elem" */ + fts3HashElem* elem, /* The element to be removed from the pH */ + int h /* Hash value for the element */ +){ + struct _fts3ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; + } + if( pH->copyKey && elem->pKey ){ + fts3HashFree(elem->pKey); + } + fts3HashFree( elem ); + pH->count--; + if( pH->count<=0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + fts3HashClear(pH); + } +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +void *sqlite3Fts3HashFind(const fts3Hash *pH, const void *pKey, int nKey){ + int h; /* A hash on key */ + fts3HashElem *elem; /* The element that matches key */ + int (*xHash)(const void*,int); /* The hash function */ + + if( pH==0 || pH->ht==0 ) return 0; + xHash = ftsHashFunction(pH->keyClass); + assert( xHash!=0 ); + h = (*xHash)(pKey,nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + elem = fts3FindElementByHash(pH,pKey,nKey, h & (pH->htsize-1)); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey,nKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created. A copy of the key is made if the copyKey +** flag is set. NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +void *sqlite3Fts3HashInsert( + fts3Hash *pH, /* The hash table to insert into */ + const void *pKey, /* The key */ + int nKey, /* Number of bytes in the key */ + void *data /* The data */ +){ + int hraw; /* Raw hash value of the key */ + int h; /* the hash of the key modulo hash table size */ + fts3HashElem *elem; /* Used to loop thru the element list */ + fts3HashElem *new_elem; /* New element added to the pH */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( pH!=0 ); + xHash = ftsHashFunction(pH->keyClass); + assert( xHash!=0 ); + hraw = (*xHash)(pKey, nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + elem = fts3FindElementByHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + fts3RemoveElementByHash(pH,elem,h); + }else{ + elem->data = data; + } + return old_data; + } + if( data==0 ) return 0; + new_elem = (fts3HashElem*)fts3HashMalloc( sizeof(fts3HashElem) ); + if( new_elem==0 ) return data; + if( pH->copyKey && pKey!=0 ){ + new_elem->pKey = fts3HashMalloc( nKey ); + if( new_elem->pKey==0 ){ + fts3HashFree(new_elem); + return data; + } + memcpy((void*)new_elem->pKey, pKey, nKey); + }else{ + new_elem->pKey = (void*)pKey; + } + new_elem->nKey = nKey; + pH->count++; + if( pH->htsize==0 ){ + fts3Rehash(pH,8); + if( pH->htsize==0 ){ + pH->count = 0; + fts3HashFree(new_elem); + return data; + } + } + if( pH->count > pH->htsize ){ + fts3Rehash(pH,pH->htsize*2); + } + assert( pH->htsize>0 ); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + fts3HashInsertElement(pH, &pH->ht[h], new_elem); + new_elem->data = data; + return 0; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.h new file mode 100644 index 0000000..e01954e --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_hash.h @@ -0,0 +1,110 @@ +/* +** 2001 September 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 is the header file for the generic hash-table implemenation +** used in SQLite. We've modified it slightly to serve as a standalone +** hash table implementation for the full-text indexing module. +** +*/ +#ifndef _FTS3_HASH_H_ +#define _FTS3_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct fts3Hash fts3Hash; +typedef struct fts3HashElem fts3HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct fts3Hash { + char keyClass; /* HASH_INT, _POINTER, _STRING, _BINARY */ + char copyKey; /* True if copy of key made on insert */ + int count; /* Number of entries in this table */ + fts3HashElem *first; /* The first element of the array */ + int htsize; /* Number of buckets in the hash table */ + struct _fts3ht { /* the hash table */ + int count; /* Number of entries with this hash */ + fts3HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct fts3HashElem { + fts3HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** There are 2 different modes of operation for a hash table: +** +** FTS3_HASH_STRING pKey points to a string that is nKey bytes long +** (including the null-terminator, if any). Case +** is respected in comparisons. +** +** FTS3_HASH_BINARY pKey points to binary data nKey bytes long. +** memcmp() is used to compare keys. +** +** A copy of the key is made if the copyKey parameter to fts3HashInit is 1. +*/ +#define FTS3_HASH_STRING 1 +#define FTS3_HASH_BINARY 2 + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +void sqlite3Fts3HashInit(fts3Hash*, int keytype, int copyKey); +void *sqlite3Fts3HashInsert(fts3Hash*, const void *pKey, int nKey, void *pData); +void *sqlite3Fts3HashFind(const fts3Hash*, const void *pKey, int nKey); +void sqlite3Fts3HashClear(fts3Hash*); + +/* +** Shorthand for the functions above +*/ +#define fts3HashInit sqlite3Fts3HashInit +#define fts3HashInsert sqlite3Fts3HashInsert +#define fts3HashFind sqlite3Fts3HashFind +#define fts3HashClear sqlite3Fts3HashClear + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** fts3Hash h; +** fts3HashElem *p; +** ... +** for(p=fts3HashFirst(&h); p; p=fts3HashNext(p)){ +** SomeStructure *pData = fts3HashData(p); +** // do something with pData +** } +*/ +#define fts3HashFirst(H) ((H)->first) +#define fts3HashNext(E) ((E)->next) +#define fts3HashData(E) ((E)->data) +#define fts3HashKey(E) ((E)->pKey) +#define fts3HashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define fts3HashCount(H) ((H)->count) + +#endif /* _FTS3_HASH_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_icu.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_icu.c new file mode 100644 index 0000000..e2d040c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_icu.c @@ -0,0 +1,258 @@ +/* +** 2007 June 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 implements a tokenizer for fts3 based on the ICU library. +** +** $Id: fts3_icu.c,v 1.2 2007/10/24 21:52:37 shess Exp $ +*/ + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) +#ifdef SQLITE_ENABLE_ICU + +#include +#include +#include "fts3_tokenizer.h" + +#include +#include +#include +#include + +typedef struct IcuTokenizer IcuTokenizer; +typedef struct IcuCursor IcuCursor; + +struct IcuTokenizer { + sqlite3_tokenizer base; + char *zLocale; +}; + +struct IcuCursor { + sqlite3_tokenizer_cursor base; + + UBreakIterator *pIter; /* ICU break-iterator object */ + int nChar; /* Number of UChar elements in pInput */ + UChar *aChar; /* Copy of input using utf-16 encoding */ + int *aOffset; /* Offsets of each character in utf-8 input */ + + int nBuffer; + char *zBuffer; + + int iToken; +}; + +/* +** Create a new tokenizer instance. +*/ +static int icuCreate( + int argc, /* Number of entries in argv[] */ + const char * const *argv, /* Tokenizer creation arguments */ + sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ +){ + IcuTokenizer *p; + int n = 0; + + if( argc>0 ){ + n = strlen(argv[0])+1; + } + p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n); + if( !p ){ + return SQLITE_NOMEM; + } + memset(p, 0, sizeof(IcuTokenizer)); + + if( n ){ + p->zLocale = (char *)&p[1]; + memcpy(p->zLocale, argv[0], n); + } + + *ppTokenizer = (sqlite3_tokenizer *)p; + + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int icuDestroy(sqlite3_tokenizer *pTokenizer){ + IcuTokenizer *p = (IcuTokenizer *)pTokenizer; + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is pInput[0..nBytes-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int icuOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *zInput, /* Input string */ + int nInput, /* Length of zInput in bytes */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + IcuTokenizer *p = (IcuTokenizer *)pTokenizer; + IcuCursor *pCsr; + + const int32_t opt = U_FOLD_CASE_DEFAULT; + UErrorCode status = U_ZERO_ERROR; + int nChar; + + UChar32 c; + int iInput = 0; + int iOut = 0; + + *ppCursor = 0; + + if( -1 == nInput ) nInput = strlen(nInput); + nChar = nInput+1; + pCsr = (IcuCursor *)sqlite3_malloc( + sizeof(IcuCursor) + /* IcuCursor */ + nChar * sizeof(UChar) + /* IcuCursor.aChar[] */ + (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ + ); + if( !pCsr ){ + return SQLITE_NOMEM; + } + memset(pCsr, 0, sizeof(IcuCursor)); + pCsr->aChar = (UChar *)&pCsr[1]; + pCsr->aOffset = (int *)&pCsr->aChar[nChar]; + + pCsr->aOffset[iOut] = iInput; + U8_NEXT(zInput, iInput, nInput, c); + while( c>0 ){ + int isError = 0; + c = u_foldCase(c, opt); + U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); + if( isError ){ + sqlite3_free(pCsr); + return SQLITE_ERROR; + } + pCsr->aOffset[iOut] = iInput; + + if( iInputpIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status); + if( !U_SUCCESS(status) ){ + sqlite3_free(pCsr); + return SQLITE_ERROR; + } + pCsr->nChar = iOut; + + ubrk_first(pCsr->pIter); + *ppCursor = (sqlite3_tokenizer_cursor *)pCsr; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to icuOpen(). +*/ +static int icuClose(sqlite3_tokenizer_cursor *pCursor){ + IcuCursor *pCsr = (IcuCursor *)pCursor; + ubrk_close(pCsr->pIter); + sqlite3_free(pCsr->zBuffer); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* +** Extract the next token from a tokenization cursor. +*/ +static int icuNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ + const char **ppToken, /* OUT: *ppToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + IcuCursor *pCsr = (IcuCursor *)pCursor; + + int iStart = 0; + int iEnd = 0; + int nByte = 0; + + while( iStart==iEnd ){ + UChar32 c; + + iStart = ubrk_current(pCsr->pIter); + iEnd = ubrk_next(pCsr->pIter); + if( iEnd==UBRK_DONE ){ + return SQLITE_DONE; + } + + while( iStartaChar, iWhite, pCsr->nChar, c); + if( u_isspace(c) ){ + iStart = iWhite; + }else{ + break; + } + } + assert(iStart<=iEnd); + } + + do { + UErrorCode status = U_ZERO_ERROR; + if( nByte ){ + char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte); + if( !zNew ){ + return SQLITE_NOMEM; + } + pCsr->zBuffer = zNew; + pCsr->nBuffer = nByte; + } + + u_strToUTF8( + pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */ + &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */ + &status /* Output success/failure */ + ); + } while( nByte>pCsr->nBuffer ); + + *ppToken = pCsr->zBuffer; + *pnBytes = nByte; + *piStartOffset = pCsr->aOffset[iStart]; + *piEndOffset = pCsr->aOffset[iEnd]; + *piPosition = pCsr->iToken++; + + return SQLITE_OK; +} + +/* +** 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 */ +}; + +/* +** Set *ppModule to point at the implementation of the ICU tokenizer. +*/ +void sqlite3Fts3IcuTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &icuTokenizerModule; +} + +#endif /* defined(SQLITE_ENABLE_ICU) */ +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_porter.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_porter.c new file mode 100644 index 0000000..6ff67a9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_porter.c @@ -0,0 +1,642 @@ +/* +** 2006 September 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. +** +************************************************************************* +** Implementation of the full-text-search tokenizer that implements +** a Porter stemmer. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS3 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS3 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) + + +#include +#include +#include +#include +#include + +#include "fts3_tokenizer.h" + +/* +** Class derived from sqlite3_tokenizer +*/ +typedef struct porter_tokenizer { + sqlite3_tokenizer base; /* Base class */ +} porter_tokenizer; + +/* +** Class derived from sqlit3_tokenizer_cursor +*/ +typedef struct porter_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *zInput; /* input we are tokenizing */ + int nInput; /* size of the input */ + int iOffset; /* current position in zInput */ + int iToken; /* index of next token to be returned */ + char *zToken; /* storage for current token */ + int nAllocated; /* space allocated to zToken buffer */ +} porter_tokenizer_cursor; + + +/* Forward declaration */ +static const sqlite3_tokenizer_module porterTokenizerModule; + + +/* +** Create a new tokenizer instance. +*/ +static int porterCreate( + int argc, const char * const *argv, + sqlite3_tokenizer **ppTokenizer +){ + porter_tokenizer *t; + t = (porter_tokenizer *) sqlite3_malloc(sizeof(*t)); + if( t==NULL ) return SQLITE_NOMEM; + memset(t, 0, sizeof(*t)); + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int porterDestroy(sqlite3_tokenizer *pTokenizer){ + sqlite3_free(pTokenizer); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is zInput[0..nInput-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int porterOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *zInput, int nInput, /* String to be tokenized */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + porter_tokenizer_cursor *c; + + c = (porter_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); + if( c==NULL ) return SQLITE_NOMEM; + + c->zInput = zInput; + if( zInput==0 ){ + c->nInput = 0; + }else if( nInput<0 ){ + c->nInput = (int)strlen(zInput); + }else{ + c->nInput = nInput; + } + c->iOffset = 0; /* start tokenizing at the beginning */ + c->iToken = 0; + c->zToken = NULL; /* no space allocated, yet. */ + c->nAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** porterOpen() above. +*/ +static int porterClose(sqlite3_tokenizer_cursor *pCursor){ + porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; + sqlite3_free(c->zToken); + sqlite3_free(c); + return SQLITE_OK; +} +/* +** Vowel or consonant +*/ +static const char cType[] = { + 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 2, 1 +}; + +/* +** isConsonant() and isVowel() determine if their first character in +** the string they point to is a consonant or a vowel, according +** to Porter ruls. +** +** A consonate is any letter other than 'a', 'e', 'i', 'o', or 'u'. +** 'Y' is a consonant unless it follows another consonant, +** in which case it is a vowel. +** +** In these routine, the letters are in reverse order. So the 'y' rule +** is that 'y' is a consonant unless it is followed by another +** consonent. +*/ +static int isVowel(const char*); +static int isConsonant(const char *z){ + int j; + char x = *z; + if( x==0 ) return 0; + assert( x>='a' && x<='z' ); + j = cType[x-'a']; + if( j<2 ) return j; + return z[1]==0 || isVowel(z + 1); +} +static int isVowel(const char *z){ + int j; + char x = *z; + if( x==0 ) return 0; + assert( x>='a' && x<='z' ); + j = cType[x-'a']; + if( j<2 ) return 1-j; + return isConsonant(z + 1); +} + +/* +** Let any sequence of one or more vowels be represented by V and let +** C be sequence of one or more consonants. Then every word can be +** represented as: +** +** [C] (VC){m} [V] +** +** In prose: A word is an optional consonant followed by zero or +** vowel-consonant pairs followed by an optional vowel. "m" is the +** number of vowel consonant pairs. This routine computes the value +** of m for the first i bytes of a word. +** +** Return true if the m-value for z is 1 or more. In other words, +** return true if z contains at least one vowel that is followed +** by a consonant. +** +** In this routine z[] is in reverse order. So we are really looking +** for an instance of of a consonant followed by a vowel. +*/ +static int m_gt_0(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* Like mgt0 above except we are looking for a value of m which is +** exactly 1 +*/ +static int m_eq_1(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + if( *z==0 ) return 0; + while( isVowel(z) ){ z++; } + if( *z==0 ) return 1; + while( isConsonant(z) ){ z++; } + return *z==0; +} + +/* Like mgt0 above except we are looking for a value of m>1 instead +** or m>0 +*/ +static int m_gt_1(const char *z){ + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + if( *z==0 ) return 0; + while( isVowel(z) ){ z++; } + if( *z==0 ) return 0; + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* +** Return TRUE if there is a vowel anywhere within z[0..n-1] +*/ +static int hasVowel(const char *z){ + while( isConsonant(z) ){ z++; } + return *z!=0; +} + +/* +** Return TRUE if the word ends in a double consonant. +** +** The text is reversed here. So we are really looking at +** the first two characters of z[]. +*/ +static int doubleConsonant(const char *z){ + return isConsonant(z) && z[0]==z[1] && isConsonant(z+1); +} + +/* +** Return TRUE if the word ends with three letters which +** are consonant-vowel-consonent and where the final consonant +** is not 'w', 'x', or 'y'. +** +** The word is reversed here. So we are really checking the +** first three letters and the first one cannot be in [wxy]. +*/ +static int star_oh(const char *z){ + return + z[0]!=0 && isConsonant(z) && + z[0]!='w' && z[0]!='x' && z[0]!='y' && + z[1]!=0 && isVowel(z+1) && + z[2]!=0 && isConsonant(z+2); +} + +/* +** If the word ends with zFrom and xCond() is true for the stem +** of the word that preceeds the zFrom ending, then change the +** ending to zTo. +** +** The input word *pz and zFrom are both in reverse order. zTo +** is in normal order. +** +** Return TRUE if zFrom matches. Return FALSE if zFrom does not +** match. Not that TRUE is returned even if xCond() fails and +** no substitution occurs. +*/ +static int stem( + char **pz, /* The word being stemmed (Reversed) */ + const char *zFrom, /* If the ending matches this... (Reversed) */ + const char *zTo, /* ... change the ending to this (not reversed) */ + int (*xCond)(const char*) /* Condition that must be true */ +){ + char *z = *pz; + while( *zFrom && *zFrom==*z ){ z++; zFrom++; } + if( *zFrom!=0 ) return 0; + if( xCond && !xCond(z) ) return 1; + while( *zTo ){ + *(--z) = *(zTo++); + } + *pz = z; + return 1; +} + +/* +** This is the fallback stemmer used when the porter stemmer is +** inappropriate. The input word is copied into the output with +** US-ASCII case folding. If the input word is too long (more +** than 20 bytes if it contains no digits or more than 6 bytes if +** it contains digits) then word is truncated to 20 or 6 bytes +** by taking 10 or 3 bytes from the beginning and end. +*/ +static void copy_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){ + int i, mx, j; + int hasDigit = 0; + for(i=0; i='A' && c<='Z' ){ + zOut[i] = c - 'A' + 'a'; + }else{ + if( c>='0' && c<='9' ) hasDigit = 1; + zOut[i] = c; + } + } + mx = hasDigit ? 3 : 10; + if( nIn>mx*2 ){ + for(j=mx, i=nIn-mx; i=sizeof(zReverse)-7 ){ + /* The word is too big or too small for the porter stemmer. + ** Fallback to the copy stemmer */ + copy_stemmer(zIn, nIn, zOut, pnOut); + return; + } + for(i=0, j=sizeof(zReverse)-6; i='A' && c<='Z' ){ + zReverse[j] = c + 'a' - 'A'; + }else if( c>='a' && c<='z' ){ + zReverse[j] = c; + }else{ + /* The use of a character not in [a-zA-Z] means that we fallback + ** to the copy stemmer */ + copy_stemmer(zIn, nIn, zOut, pnOut); + return; + } + } + memset(&zReverse[sizeof(zReverse)-5], 0, 5); + z = &zReverse[j+1]; + + + /* Step 1a */ + if( z[0]=='s' ){ + if( + !stem(&z, "sess", "ss", 0) && + !stem(&z, "sei", "i", 0) && + !stem(&z, "ss", "ss", 0) + ){ + z++; + } + } + + /* Step 1b */ + z2 = z; + if( stem(&z, "dee", "ee", m_gt_0) ){ + /* Do nothing. The work was all in the test */ + }else if( + (stem(&z, "gni", "", hasVowel) || stem(&z, "de", "", hasVowel)) + && z!=z2 + ){ + if( stem(&z, "ta", "ate", 0) || + stem(&z, "lb", "ble", 0) || + stem(&z, "zi", "ize", 0) ){ + /* Do nothing. The work was all in the test */ + }else if( doubleConsonant(z) && (*z!='l' && *z!='s' && *z!='z') ){ + z++; + }else if( m_eq_1(z) && star_oh(z) ){ + *(--z) = 'e'; + } + } + + /* Step 1c */ + if( z[0]=='y' && hasVowel(z+1) ){ + z[0] = 'i'; + } + + /* Step 2 */ + switch( z[1] ){ + case 'a': + stem(&z, "lanoita", "ate", m_gt_0) || + stem(&z, "lanoit", "tion", m_gt_0); + break; + case 'c': + stem(&z, "icne", "ence", m_gt_0) || + stem(&z, "icna", "ance", m_gt_0); + break; + case 'e': + stem(&z, "rezi", "ize", m_gt_0); + break; + case 'g': + stem(&z, "igol", "log", m_gt_0); + break; + case 'l': + stem(&z, "ilb", "ble", m_gt_0) || + stem(&z, "illa", "al", m_gt_0) || + stem(&z, "iltne", "ent", m_gt_0) || + stem(&z, "ile", "e", m_gt_0) || + stem(&z, "ilsuo", "ous", m_gt_0); + break; + case 'o': + stem(&z, "noitazi", "ize", m_gt_0) || + stem(&z, "noita", "ate", m_gt_0) || + stem(&z, "rota", "ate", m_gt_0); + break; + case 's': + stem(&z, "msila", "al", m_gt_0) || + stem(&z, "ssenevi", "ive", m_gt_0) || + stem(&z, "ssenluf", "ful", m_gt_0) || + stem(&z, "ssensuo", "ous", m_gt_0); + break; + case 't': + stem(&z, "itila", "al", m_gt_0) || + stem(&z, "itivi", "ive", m_gt_0) || + stem(&z, "itilib", "ble", m_gt_0); + break; + } + + /* Step 3 */ + switch( z[0] ){ + case 'e': + stem(&z, "etaci", "ic", m_gt_0) || + stem(&z, "evita", "", m_gt_0) || + stem(&z, "ezila", "al", m_gt_0); + break; + case 'i': + stem(&z, "itici", "ic", m_gt_0); + break; + case 'l': + stem(&z, "laci", "ic", m_gt_0) || + stem(&z, "luf", "", m_gt_0); + break; + case 's': + stem(&z, "ssen", "", m_gt_0); + break; + } + + /* Step 4 */ + switch( z[1] ){ + case 'a': + if( z[0]=='l' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'c': + if( z[0]=='e' && z[2]=='n' && (z[3]=='a' || z[3]=='e') && m_gt_1(z+4) ){ + z += 4; + } + break; + case 'e': + if( z[0]=='r' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'i': + if( z[0]=='c' && m_gt_1(z+2) ){ + z += 2; + } + break; + case 'l': + if( z[0]=='e' && z[2]=='b' && (z[3]=='a' || z[3]=='i') && m_gt_1(z+4) ){ + z += 4; + } + break; + case 'n': + if( z[0]=='t' ){ + if( z[2]=='a' ){ + if( m_gt_1(z+3) ){ + z += 3; + } + }else if( z[2]=='e' ){ + stem(&z, "tneme", "", m_gt_1) || + stem(&z, "tnem", "", m_gt_1) || + stem(&z, "tne", "", m_gt_1); + } + } + break; + case 'o': + if( z[0]=='u' ){ + if( m_gt_1(z+2) ){ + z += 2; + } + }else if( z[3]=='s' || z[3]=='t' ){ + stem(&z, "noi", "", m_gt_1); + } + break; + case 's': + if( z[0]=='m' && z[2]=='i' && m_gt_1(z+3) ){ + z += 3; + } + break; + case 't': + stem(&z, "eta", "", m_gt_1) || + stem(&z, "iti", "", m_gt_1); + break; + case 'u': + if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){ + z += 3; + } + break; + case 'v': + case 'z': + if( z[0]=='e' && z[2]=='i' && m_gt_1(z+3) ){ + z += 3; + } + break; + } + + /* Step 5a */ + if( z[0]=='e' ){ + if( m_gt_1(z+1) ){ + z++; + }else if( m_eq_1(z+1) && !star_oh(z+1) ){ + z++; + } + } + + /* Step 5b */ + if( m_gt_1(z) && z[0]=='l' && z[1]=='l' ){ + z++; + } + + /* z[] is now the stemmed word in reverse order. Flip it back + ** around into forward order and return. + */ + *pnOut = i = strlen(z); + zOut[i] = 0; + while( *z ){ + zOut[--i] = *(z++); + } +} + +/* +** Characters that can be part of a token. We assume any character +** whose value is greater than 0x80 (any UTF character) can be +** part of a token. In other words, delimiters all must have +** values of 0x7f or lower. +*/ +static const char porterIdChar[] = { +/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ +}; +#define isDelim(C) (((ch=C)&0x80)==0 && (ch<0x30 || !porterIdChar[ch-0x30])) + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to porterOpen(). +*/ +static int porterNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by porterOpen */ + const char **pzToken, /* OUT: *pzToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + porter_tokenizer_cursor *c = (porter_tokenizer_cursor *) pCursor; + const char *z = c->zInput; + + while( c->iOffsetnInput ){ + int iStartOffset, ch; + + /* Scan past delimiter characters */ + while( c->iOffsetnInput && isDelim(z[c->iOffset]) ){ + c->iOffset++; + } + + /* Count non-delimiter characters. */ + iStartOffset = c->iOffset; + while( c->iOffsetnInput && !isDelim(z[c->iOffset]) ){ + c->iOffset++; + } + + if( c->iOffset>iStartOffset ){ + int n = c->iOffset-iStartOffset; + if( n>c->nAllocated ){ + c->nAllocated = n+20; + c->zToken = sqlite3_realloc(c->zToken, c->nAllocated); + if( c->zToken==NULL ) return SQLITE_NOMEM; + } + porter_stemmer(&z[iStartOffset], n, c->zToken, pnBytes); + *pzToken = c->zToken; + *piStartOffset = iStartOffset; + *piEndOffset = c->iOffset; + *piPosition = c->iToken++; + return SQLITE_OK; + } + } + return SQLITE_DONE; +} + +/* +** The set of routines that implement the porter-stemmer tokenizer +*/ +static const sqlite3_tokenizer_module porterTokenizerModule = { + 0, + porterCreate, + porterDestroy, + porterOpen, + porterClose, + porterNext, +}; + +/* +** Allocate a new porter tokenizer. Return a pointer to the new +** tokenizer in *ppModule +*/ +void sqlite3Fts3PorterTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &porterTokenizerModule; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.c new file mode 100644 index 0000000..ef19995 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.c @@ -0,0 +1,371 @@ +/* +** 2007 June 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 is part of an SQLite module implementing full-text search. +** This particular file implements the generic tokenizer interface. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS3 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS3 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) + +#include "sqlite3ext.h" +#ifndef SQLITE_CORE + SQLITE_EXTENSION_INIT1 +#endif + +#include "fts3_hash.h" +#include "fts3_tokenizer.h" +#include + +/* +** Implementation of the SQL scalar function for accessing the underlying +** hash table. This function may be called as follows: +** +** SELECT (); +** SELECT (, ); +** +** where is the name passed as the second argument +** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer'). +** +** If the argument is specified, it must be a blob value +** containing a pointer to be stored as the hash data corresponding +** to the string . If is not specified, then +** the string must already exist in the has table. Otherwise, +** an error is returned. +** +** Whether or not the argument is specified, the value returned +** is a blob containing the pointer stored as the hash data corresponding +** to string (after the hash-table is updated, if applicable). +*/ +static void scalarFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts3Hash *pHash; + void *pPtr = 0; + const unsigned char *zName; + int nName; + + assert( argc==1 || argc==2 ); + + pHash = (fts3Hash *)sqlite3_user_data(context); + + zName = sqlite3_value_text(argv[0]); + nName = sqlite3_value_bytes(argv[0])+1; + + if( argc==2 ){ + void *pOld; + int n = sqlite3_value_bytes(argv[1]); + if( n!=sizeof(pPtr) ){ + sqlite3_result_error(context, "argument type mismatch", -1); + return; + } + pPtr = *(void **)sqlite3_value_blob(argv[1]); + pOld = sqlite3Fts3HashInsert(pHash, (void *)zName, nName, pPtr); + if( pOld==pPtr ){ + sqlite3_result_error(context, "out of memory", -1); + return; + } + }else{ + pPtr = sqlite3Fts3HashFind(pHash, zName, nName); + if( !pPtr ){ + char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + } + + sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT); +} + +#ifdef SQLITE_TEST + +#include +#include + +/* +** Implementation of a special SQL scalar function for testing tokenizers +** designed to be used in concert with the Tcl testing framework. This +** function must be called with two arguments: +** +** SELECT (, ); +** SELECT (, ); +** +** where is the name passed as the second argument +** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') +** concatenated with the string '_test' (e.g. 'fts3_tokenizer_test'). +** +** The return value is a string that may be interpreted as a Tcl +** list. For each token in the , three elements are +** added to the returned list. The first is the token position, the +** second is the token text (folded, stemmed, etc.) and the third is the +** substring of associated with the token. For example, +** using the built-in "simple" tokenizer: +** +** SELECT fts_tokenizer_test('simple', 'I don't see how'); +** +** will return the string: +** +** "{0 i I 1 dont don't 2 see see 3 how how}" +** +*/ +static void testFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + fts3Hash *pHash; + sqlite3_tokenizer_module *p; + sqlite3_tokenizer *pTokenizer = 0; + sqlite3_tokenizer_cursor *pCsr = 0; + + const char *zErr = 0; + + const char *zName; + int nName; + const char *zInput; + int nInput; + + const char *zArg = 0; + + const char *zToken; + int nToken; + int iStart; + int iEnd; + int iPos; + + Tcl_Obj *pRet; + + assert( argc==2 || argc==3 ); + + nName = sqlite3_value_bytes(argv[0]); + zName = (const char *)sqlite3_value_text(argv[0]); + nInput = sqlite3_value_bytes(argv[argc-1]); + zInput = (const char *)sqlite3_value_text(argv[argc-1]); + + if( argc==3 ){ + zArg = (const char *)sqlite3_value_text(argv[1]); + } + + pHash = (fts3Hash *)sqlite3_user_data(context); + 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); + return; + } + + pRet = Tcl_NewObj(); + Tcl_IncrRefCount(pRet); + + if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ + zErr = "error in xCreate()"; + goto finish; + } + pTokenizer->pModule = p; + if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){ + zErr = "error in xOpen()"; + goto finish; + } + pCsr->pTokenizer = pTokenizer; + + while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ + Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); + zToken = &zInput[iStart]; + nToken = iEnd-iStart; + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zToken, nToken)); + } + + if( SQLITE_OK!=p->xClose(pCsr) ){ + zErr = "error in xClose()"; + goto finish; + } + if( SQLITE_OK!=p->xDestroy(pTokenizer) ){ + zErr = "error in xDestroy()"; + goto finish; + } + +finish: + if( zErr ){ + sqlite3_result_error(context, zErr, -1); + }else{ + sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); + } + Tcl_DecrRefCount(pRet); +} + +static +int registerTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module *p +){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts3_tokenizer(?, ?)"; + + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + sqlite3_bind_blob(pStmt, 2, &p, sizeof(p), SQLITE_STATIC); + sqlite3_step(pStmt); + + return sqlite3_finalize(pStmt); +} + +static +int queryTokenizer( + sqlite3 *db, + char *zName, + const sqlite3_tokenizer_module **pp +){ + int rc; + sqlite3_stmt *pStmt; + const char zSql[] = "SELECT fts3_tokenizer(?)"; + + *pp = 0; + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC); + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){ + memcpy(pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp)); + } + } + + return sqlite3_finalize(pStmt); +} + +void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); + +/* +** Implementation of the scalar function fts3_tokenizer_internal_test(). +** This function is used for testing only, it is not included in the +** build unless SQLITE_TEST is defined. +** +** The purpose of this is to test that the fts3_tokenizer() function +** can be used as designed by the C-code in the queryTokenizer and +** registerTokenizer() functions above. These two functions are repeated +** in the README.tokenizer file as an example, so it is important to +** test them. +** +** To run the tests, evaluate the fts3_tokenizer_internal_test() scalar +** function with no arguments. An assert() will fail if a problem is +** detected. i.e.: +** +** SELECT fts3_tokenizer_internal_test(); +** +*/ +static void intTestFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int rc; + const sqlite3_tokenizer_module *p1; + const sqlite3_tokenizer_module *p2; + sqlite3 *db = (sqlite3 *)sqlite3_user_data(context); + + /* Test the query function */ + sqlite3Fts3SimpleTokenizerModule(&p1); + rc = queryTokenizer(db, "simple", &p2); + assert( rc==SQLITE_OK ); + assert( p1==p2 ); + rc = queryTokenizer(db, "nosuchtokenizer", &p2); + assert( rc==SQLITE_ERROR ); + assert( p2==0 ); + assert( 0==strcmp(sqlite3_errmsg(db), "unknown tokenizer: nosuchtokenizer") ); + + /* Test the storage function */ + rc = registerTokenizer(db, "nosuchtokenizer", p1); + assert( rc==SQLITE_OK ); + rc = queryTokenizer(db, "nosuchtokenizer", &p2); + assert( rc==SQLITE_OK ); + assert( p2==p1 ); + + sqlite3_result_text(context, "ok", -1, SQLITE_STATIC); +} + +#endif + +/* +** Set up SQL objects in database db used to access the contents of +** the hash table pointed to by argument pHash. The hash table must +** been initialised to use string keys, and to take a private copy +** of the key when a value is inserted. i.e. by a call similar to: +** +** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); +** +** This function adds a scalar function (see header comment above +** scalarFunc() in this file for details) and, if ENABLE_TABLE is +** defined at compilation time, a temporary virtual table (see header +** comment above struct HashTableVtab) to the database schema. Both +** provide read/write access to the contents of *pHash. +** +** The third argument to this function, zName, is used as the name +** of both the scalar and, if created, the virtual table. +*/ +int sqlite3Fts3InitHashTable( + sqlite3 *db, + fts3Hash *pHash, + const char *zName +){ + int rc = SQLITE_OK; + void *p = (void *)pHash; + const int any = SQLITE_ANY; + char *zTest = 0; + char *zTest2 = 0; + +#ifdef SQLITE_TEST + void *pdb = (void *)db; + zTest = sqlite3_mprintf("%s_test", zName); + zTest2 = sqlite3_mprintf("%s_internal_test", zName); + if( !zTest || !zTest2 ){ + rc = SQLITE_NOMEM; + } +#endif + + if( rc!=SQLITE_OK + || (rc = sqlite3_create_function(db, zName, 1, any, p, scalarFunc, 0, 0)) + || (rc = sqlite3_create_function(db, zName, 2, any, p, scalarFunc, 0, 0)) +#ifdef SQLITE_TEST + || (rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0)) + || (rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0)) + || (rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0)) +#endif + ); + + sqlite3_free(zTest); + sqlite3_free(zTest2); + return rc; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.h b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.h new file mode 100644 index 0000000..4faef56 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer.h @@ -0,0 +1,145 @@ +/* +** 2006 July 10 +** +** The author disclaims copyright to this source code. +** +************************************************************************* +** Defines the interface to tokenizers used by fulltext-search. There +** are three basic components: +** +** sqlite3_tokenizer_module is a singleton defining the tokenizer +** interface functions. This is essentially the class structure for +** tokenizers. +** +** sqlite3_tokenizer is used to define a particular tokenizer, perhaps +** including customization information defined at creation time. +** +** sqlite3_tokenizer_cursor is generated by a tokenizer to generate +** tokens from a particular input. +*/ +#ifndef _FTS3_TOKENIZER_H_ +#define _FTS3_TOKENIZER_H_ + +/* TODO(shess) Only used for SQLITE_OK and SQLITE_DONE at this time. +** If tokenizers are to be allowed to call sqlite3_*() functions, then +** we will need a way to register the API consistently. +*/ +#include "sqlite3.h" + +/* +** Structures used by the tokenizer interface. When a new tokenizer +** implementation is registered, the caller provides a pointer to +** an sqlite3_tokenizer_module containing pointers to the callback +** functions that make up an implementation. +** +** When an fts3 table is created, it passes any arguments passed to +** the tokenizer clause of the CREATE VIRTUAL TABLE statement to the +** sqlite3_tokenizer_module.xCreate() function of the requested tokenizer +** implementation. The xCreate() function in turn returns an +** sqlite3_tokenizer structure representing the specific tokenizer to +** be used for the fts3 table (customized by the tokenizer clause arguments). +** +** To tokenize an input buffer, the sqlite3_tokenizer_module.xOpen() +** method is called. It returns an sqlite3_tokenizer_cursor object +** that may be used to tokenize a specific input buffer based on +** the tokenization rules supplied by a specific sqlite3_tokenizer +** object. +*/ +typedef struct sqlite3_tokenizer_module sqlite3_tokenizer_module; +typedef struct sqlite3_tokenizer sqlite3_tokenizer; +typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; + +struct sqlite3_tokenizer_module { + + /* + ** Structure version. Should always be set to 0. + */ + int iVersion; + + /* + ** Create a new tokenizer. The values in the argv[] array are the + ** arguments passed to the "tokenizer" clause of the CREATE VIRTUAL + ** TABLE statement that created the fts3 table. For example, if + ** the following SQL is executed: + ** + ** CREATE .. USING fts3( ... , tokenizer arg1 arg2) + ** + ** then argc is set to 2, and the argv[] array contains pointers + ** to the strings "arg1" and "arg2". + ** + ** This method should return either SQLITE_OK (0), or an SQLite error + ** code. If SQLITE_OK is returned, then *ppTokenizer should be set + ** to point at the newly created tokenizer structure. The generic + ** sqlite3_tokenizer.pModule variable should not be initialised by + ** this callback. The caller will do so. + */ + int (*xCreate)( + int argc, /* Size of argv array */ + const char *const*argv, /* Tokenizer argument strings */ + sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */ + ); + + /* + ** Destroy an existing tokenizer. The fts3 module calls this method + ** exactly once for each successful call to xCreate(). + */ + int (*xDestroy)(sqlite3_tokenizer *pTokenizer); + + /* + ** Create a tokenizer cursor to tokenize an input buffer. The caller + ** is responsible for ensuring that the input buffer remains valid + ** until the cursor is closed (using the xClose() method). + */ + int (*xOpen)( + sqlite3_tokenizer *pTokenizer, /* Tokenizer object */ + const char *pInput, int nBytes, /* Input buffer */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Created tokenizer cursor */ + ); + + /* + ** Destroy an existing tokenizer cursor. The fts3 module calls this + ** method exactly once for each successful call to xOpen(). + */ + int (*xClose)(sqlite3_tokenizer_cursor *pCursor); + + /* + ** Retrieve the next token from the tokenizer cursor pCursor. This + ** method should either return SQLITE_OK and set the values of the + ** "OUT" variables identified below, or SQLITE_DONE to indicate that + ** the end of the buffer has been reached, or an SQLite error code. + ** + ** *ppToken should be set to point at a buffer containing the + ** normalized version of the token (i.e. after any case-folding and/or + ** stemming has been performed). *pnBytes should be set to the length + ** of this buffer in bytes. The input text that generated the token is + ** identified by the byte offsets returned in *piStartOffset and + ** *piEndOffset. + ** + ** The buffer *ppToken is set to point at is managed by the tokenizer + ** implementation. It is only required to be valid until the next call + ** to xNext() or xClose(). + */ + /* TODO(shess) current implementation requires pInput to be + ** nul-terminated. This should either be fixed, or pInput/nBytes + ** should be converted to zInput. + */ + int (*xNext)( + sqlite3_tokenizer_cursor *pCursor, /* Tokenizer cursor */ + const char **ppToken, int *pnBytes, /* OUT: Normalized text for token */ + int *piStartOffset, /* OUT: Byte offset of token in input buffer */ + int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ + int *piPosition /* OUT: Number of tokens returned before this one */ + ); +}; + +struct sqlite3_tokenizer { + const sqlite3_tokenizer_module *pModule; /* The module for this tokenizer */ + /* Tokenizer implementations will typically add additional fields */ +}; + +struct sqlite3_tokenizer_cursor { + sqlite3_tokenizer *pTokenizer; /* Tokenizer for this cursor. */ + /* Tokenizer implementations will typically add additional fields */ +}; + +#endif /* _FTS3_TOKENIZER_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer1.c b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer1.c new file mode 100644 index 0000000..da255d9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/fts3_tokenizer1.c @@ -0,0 +1,230 @@ +/* +** 2006 Oct 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. +** +****************************************************************************** +** +** Implementation of the "simple" full-text-search tokenizer. +*/ + +/* +** The code in this file is only compiled if: +** +** * The FTS3 module is being built as an extension +** (in which case SQLITE_CORE is not defined), or +** +** * The FTS3 module is being built into the core of +** SQLite (in which case SQLITE_ENABLE_FTS3 is defined). +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) + + +#include +#include +#include +#include +#include + +#include "fts3_tokenizer.h" + +typedef struct simple_tokenizer { + sqlite3_tokenizer base; + char delim[128]; /* flag ASCII delimiters */ +} simple_tokenizer; + +typedef struct simple_tokenizer_cursor { + sqlite3_tokenizer_cursor base; + const char *pInput; /* input we are tokenizing */ + int nBytes; /* size of the input */ + int iOffset; /* current position in pInput */ + int iToken; /* index of next token to be returned */ + char *pToken; /* storage for current token */ + int nTokenAllocated; /* space allocated to zToken buffer */ +} simple_tokenizer_cursor; + + +/* Forward declaration */ +static const sqlite3_tokenizer_module simpleTokenizerModule; + +static int simpleDelim(simple_tokenizer *t, unsigned char c){ + return c<0x80 && t->delim[c]; +} + +/* +** Create a new tokenizer instance. +*/ +static int simpleCreate( + int argc, const char * const *argv, + sqlite3_tokenizer **ppTokenizer +){ + simple_tokenizer *t; + + t = (simple_tokenizer *) sqlite3_malloc(sizeof(*t)); + if( t==NULL ) return SQLITE_NOMEM; + memset(t, 0, sizeof(*t)); + + /* TODO(shess) Delimiters need to remain the same from run to run, + ** else we need to reindex. One solution would be a meta-table to + ** track such information in the database, then we'd only want this + ** information on the initial create. + */ + if( argc>1 ){ + int i, n = strlen(argv[1]); + for(i=0; i=0x80 ){ + sqlite3_free(t); + return SQLITE_ERROR; + } + t->delim[ch] = 1; + } + } else { + /* Mark non-alphanumeric ASCII characters as delimiters */ + int i; + for(i=1; i<0x80; i++){ + t->delim[i] = !isalnum(i); + } + } + + *ppTokenizer = &t->base; + return SQLITE_OK; +} + +/* +** Destroy a tokenizer +*/ +static int simpleDestroy(sqlite3_tokenizer *pTokenizer){ + sqlite3_free(pTokenizer); + return SQLITE_OK; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is pInput[0..nBytes-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int simpleOpen( + sqlite3_tokenizer *pTokenizer, /* The tokenizer */ + const char *pInput, int nBytes, /* String to be tokenized */ + sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */ +){ + simple_tokenizer_cursor *c; + + c = (simple_tokenizer_cursor *) sqlite3_malloc(sizeof(*c)); + if( c==NULL ) return SQLITE_NOMEM; + + c->pInput = pInput; + if( pInput==0 ){ + c->nBytes = 0; + }else if( nBytes<0 ){ + c->nBytes = (int)strlen(pInput); + }else{ + c->nBytes = nBytes; + } + c->iOffset = 0; /* start tokenizing at the beginning */ + c->iToken = 0; + c->pToken = NULL; /* no space allocated, yet. */ + c->nTokenAllocated = 0; + + *ppCursor = &c->base; + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** simpleOpen() above. +*/ +static int simpleClose(sqlite3_tokenizer_cursor *pCursor){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + sqlite3_free(c->pToken); + sqlite3_free(c); + return SQLITE_OK; +} + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to simpleOpen(). +*/ +static int simpleNext( + sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */ + const char **ppToken, /* OUT: *ppToken is the token text */ + int *pnBytes, /* OUT: Number of bytes in token */ + int *piStartOffset, /* OUT: Starting offset of token */ + int *piEndOffset, /* OUT: Ending offset of token */ + int *piPosition /* OUT: Position integer of token */ +){ + simple_tokenizer_cursor *c = (simple_tokenizer_cursor *) pCursor; + simple_tokenizer *t = (simple_tokenizer *) pCursor->pTokenizer; + unsigned char *p = (unsigned char *)c->pInput; + + while( c->iOffsetnBytes ){ + int iStartOffset; + + /* Scan past delimiter characters */ + while( c->iOffsetnBytes && simpleDelim(t, p[c->iOffset]) ){ + c->iOffset++; + } + + /* Count non-delimiter characters. */ + iStartOffset = c->iOffset; + while( c->iOffsetnBytes && !simpleDelim(t, p[c->iOffset]) ){ + c->iOffset++; + } + + if( c->iOffset>iStartOffset ){ + int i, n = c->iOffset-iStartOffset; + if( n>c->nTokenAllocated ){ + c->nTokenAllocated = n+20; + c->pToken = sqlite3_realloc(c->pToken, c->nTokenAllocated); + if( c->pToken==NULL ) return SQLITE_NOMEM; + } + for(i=0; ipToken[i] = ch<0x80 ? tolower(ch) : ch; + } + *ppToken = c->pToken; + *pnBytes = n; + *piStartOffset = iStartOffset; + *piEndOffset = c->iOffset; + *piPosition = c->iToken++; + + return SQLITE_OK; + } + } + return SQLITE_DONE; +} + +/* +** The set of routines that implement the simple tokenizer +*/ +static const sqlite3_tokenizer_module simpleTokenizerModule = { + 0, + simpleCreate, + simpleDestroy, + simpleOpen, + simpleClose, + simpleNext, +}; + +/* +** Allocate a new simple tokenizer. Return a pointer to the new +** tokenizer in *ppModule +*/ +void sqlite3Fts3SimpleTokenizerModule( + sqlite3_tokenizer_module const**ppModule +){ + *ppModule = &simpleTokenizerModule; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/fts3/mkfts3amal.tcl b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/mkfts3amal.tcl new file mode 100644 index 0000000..0590487 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/fts3/mkfts3amal.tcl @@ -0,0 +1,115 @@ +#!/usr/bin/tclsh +# +# This script builds a single C code file holding all of FTS3 code. +# The name of the output file is fts3amal.c. To build this file, +# first do: +# +# make target_source +# +# The make target above moves all of the source code files into +# a subdirectory named "tsrc". (This script expects to find the files +# there and will not work if they are not found.) +# +# After the "tsrc" directory has been created and populated, run +# this script: +# +# tclsh mkfts3amal.tcl +# +# The amalgamated FTS3 code will be written into fts3amal.c +# + +# Open the output file and write a header comment at the beginning +# of the file. +# +set out [open fts3amal.c w] +set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1] +puts $out [subst \ +{/****************************************************************************** +** This file is an amalgamation of separate C source files from the SQLite +** Full Text Search extension 2 (fts3). By combining all the individual C +** code files into this single large file, the entire code can be compiled +** as a one translation unit. This allows many compilers to do optimizations +** that would not be possible if the files were compiled separately. It also +** makes the code easier to import into other projects. +** +** This amalgamation was generated on $today. +*/}] + +# These are the header files used by FTS3. The first time any of these +# files are seen in a #include statement in the C code, include the complete +# text of the file in-line. The file only needs to be included once. +# +foreach hdr { + fts3.h + fts3_hash.h + fts3_tokenizer.h + sqlite3.h + sqlite3ext.h +} { + set available_hdr($hdr) 1 +} + +# 78 stars used for comment formatting. +set s78 \ +{*****************************************************************************} + +# Insert a comment into the code +# +proc section_comment {text} { + global out s78 + set n [string length $text] + set nstar [expr {60 - $n}] + set stars [string range $s78 0 $nstar] + puts $out "/************** $text $stars/" +} + +# Read the source file named $filename and write it into the +# sqlite3.c output file. If any #include statements are seen, +# process them approprately. +# +proc copy_file {filename} { + global seen_hdr available_hdr out + set tail [file tail $filename] + section_comment "Begin file $tail" + set in [open $filename r] + while {![eof $in]} { + set line [gets $in] + if {[regexp {^#\s*include\s+["<]([^">]+)[">]} $line all hdr]} { + if {[info exists available_hdr($hdr)]} { + if {$available_hdr($hdr)} { + section_comment "Include $hdr in the middle of $tail" + copy_file tsrc/$hdr + section_comment "Continuing where we left off in $tail" + } + } elseif {![info exists seen_hdr($hdr)]} { + set seen_hdr($hdr) 1 + puts $out $line + } + } elseif {[regexp {^#ifdef __cplusplus} $line]} { + puts $out "#if 0" + } elseif {[regexp {^#line} $line]} { + # Skip #line directives. + } else { + puts $out $line + } + } + close $in + section_comment "End of $tail" +} + + +# Process the source files. Process files containing commonly +# used subroutines first in order to help the compiler find +# inlining opportunities. +# +foreach file { + fts3.c + fts3_hash.c + fts3_porter.c + fts3_tokenizer.c + fts3_tokenizer1.c +} { + copy_file tsrc/$file +} + +close $out diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Entries b/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Entries new file mode 100644 index 0000000..bd8993c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Entries @@ -0,0 +1,3 @@ +/README.txt/1.2/Fri Jun 22 15:21:16 2007// +/icu.c/1.7/Thu Dec 13 21:54:11 2007// +D diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Repository b/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Repository new file mode 100644 index 0000000..e07a9e2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Repository @@ -0,0 +1 @@ +sqlite/ext/icu diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Root b/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Root new file mode 100644 index 0000000..a3ae5d0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/icu/CVS/Root @@ -0,0 +1 @@ +:pserver:drh@sqlite.org:/sqlite diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/icu/README.txt b/client/src/thirdparty/sqlite-3.4.2/ext/icu/README.txt new file mode 100644 index 0000000..5c995cc --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/icu/README.txt @@ -0,0 +1,170 @@ + +This directory contains source code for the SQLite "ICU" extension, an +integration of the "International Components for Unicode" library with +SQLite. Documentation follows. + + 1. Features + + 1.1 SQL Scalars upper() and lower() + 1.2 Unicode Aware LIKE Operator + 1.3 ICU Collation Sequences + 1.4 SQL REGEXP Operator + + 2. Compilation and Usage + + 3. Bugs, Problems and Security Issues + + 3.1 The "case_sensitive_like" Pragma + 3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro + 3.3 Collation Sequence Security Issue + + +1. FEATURES + + 1.1 SQL Scalars upper() and lower() + + SQLite's built-in implementations of these two functions only + provide case mapping for the 26 letters used in the English + language. The ICU based functions provided by this extension + provide case mapping, where defined, for the full range of + unicode characters. + + ICU provides two types of case mapping, "general" case mapping and + "language specific". Refer to ICU documentation for the differences + between the two. Specifically: + + http://www.icu-project.org/userguide/caseMappings.html + http://www.icu-project.org/userguide/posix.html#case_mappings + + To utilise "general" case mapping, the upper() or lower() scalar + functions are invoked with one argument: + + upper('ABC') -> 'abc' + lower('abc') -> 'ABC' + + To access ICU "language specific" case mapping, upper() or lower() + should be invoked with two arguments. The second argument is the name + of the locale to use. Passing an empty string ("") or SQL NULL value + as the second argument is the same as invoking the 1 argument version + of upper() or lower(): + + lower('I', 'en_us') -> 'i' + lower('I', 'tr_tr') -> 'ı' (small dotless i) + + 1.2 Unicode Aware LIKE Operator + + Similarly to the upper() and lower() functions, the built-in SQLite LIKE + operator understands case equivalence for the 26 letters of the English + language alphabet. The implementation of LIKE included in this + extension uses the ICU function u_foldCase() to provide case + independent comparisons for the full range of unicode characters. + + The U_FOLD_CASE_DEFAULT flag is passed to u_foldCase(), meaning the + dotless 'I' character used in the Turkish language is considered + to be in the same equivalence class as the dotted 'I' character + used by many languages (including English). + + 1.3 ICU Collation Sequences + + A special SQL scalar function, icu_load_collation() is provided that + may be used to register ICU collation sequences with SQLite. It + is always called with exactly two arguments, the ICU locale + identifying the collation sequence to ICU, and the name of the + SQLite collation sequence to create. For example, to create an + SQLite collation sequence named "turkish" using Turkish language + sorting rules, the SQL statement: + + SELECT icu_load_collation('tr_TR', 'turkish'); + + Or, for Australian English: + + SELECT icu_load_collation('en_AU', 'australian'); + + The identifiers "turkish" and "australian" may then be used + as collation sequence identifiers in SQL statements: + + CREATE TABLE aust_turkish_penpals( + australian_penpal_name TEXT COLLATE australian, + turkish_penpal_name TEXT COLLATE turkish + ); + + 1.4 SQL REGEXP Operator + + This extension provides an implementation of the SQL binary + comparision operator "REGEXP", based on the regular expression functions + provided by the ICU library. The syntax of the operator is as described + in SQLite documentation: + + REGEXP + + This extension uses the ICU defaults for regular expression matching + behaviour. Specifically, this means that: + + * Matching is case-sensitive, + * Regular expression comments are not allowed within patterns, and + * The '^' and '$' characters match the beginning and end of the + argument, not the beginning and end of lines within + the argument. + + Even more specifically, the value passed to the "flags" parameter + of ICU C function uregex_open() is 0. + + +2 COMPILATION AND USAGE + + The easiest way to compile and use the ICU extension is to build + and use it as a dynamically loadable SQLite extension. To do this + using gcc on *nix: + + gcc -shared icu.c `icu-config --ldflags` -o libSqliteIcu.so + + You may need to add "-I" flags so that gcc can find sqlite3ext.h + and sqlite3.h. The resulting shared lib, libSqliteIcu.so, may be + loaded into sqlite in the same way as any other dynamically loadable + extension. + + +3 BUGS, PROBLEMS AND SECURITY ISSUES + + 3.1 The "case_sensitive_like" Pragma + + This extension does not work well with the "case_sensitive_like" + pragma. If this pragma is used before the ICU extension is loaded, + then the pragma has no effect. If the pragma is used after the ICU + extension is loaded, then SQLite ignores the ICU implementation and + always uses the built-in LIKE operator. + + The ICU extension LIKE operator is always case insensitive. + + 3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro + + Passing very long patterns to the built-in SQLite LIKE operator can + cause a stack overflow. To curb this problem, SQLite defines the + SQLITE_MAX_LIKE_PATTERN_LENGTH macro as the maximum length of a + pattern in bytes (irrespective of encoding). The default value is + defined in internal header file "limits.h". + + The ICU extension LIKE implementation suffers from the same + problem and uses the same solution. However, since the ICU extension + code does not include the SQLite file "limits.h", modifying + the default value therein does not affect the ICU extension. + The default value of SQLITE_MAX_LIKE_PATTERN_LENGTH used by + the ICU extension LIKE operator is 50000, defined in source + file "icu.c". + + 3.3 Collation Sequence Security Issue + + Internally, SQLite assumes that indices stored in database files + are sorted according to the collation sequence indicated by the + SQL schema. Changing the definition of a collation sequence after + an index has been built is therefore equivalent to database + corruption. The SQLite library is not very well tested under + these conditions, and may contain potential buffer overruns + or other programming errors that could be exploited by a malicious + programmer. + + If the ICU extension is used in an environment where potentially + malicious users may execute arbitrary SQL (i.e. gears), they + should be prevented from invoking the icu_load_collation() function, + possibly using the authorisation callback. + diff --git a/client/src/thirdparty/sqlite-3.4.2/ext/icu/icu.c b/client/src/thirdparty/sqlite-3.4.2/ext/icu/icu.c new file mode 100644 index 0000000..c673341 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ext/icu/icu.c @@ -0,0 +1,499 @@ +/* +** 2007 May 6 +** +** 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. +** +************************************************************************* +** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $ +** +** This file implements an integration between the ICU library +** ("International Components for Unicode", an open-source library +** for handling unicode data) and SQLite. The integration uses +** ICU to provide the following to SQLite: +** +** * An implementation of the SQL regexp() function (and hence REGEXP +** operator) using the ICU uregex_XX() APIs. +** +** * Implementations of the SQL scalar upper() and lower() functions +** for case mapping. +** +** * Integration of ICU and SQLite collation seqences. +** +** * An implementation of the LIKE operator that uses ICU to +** provide case-independent matching. +*/ + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) + +/* Include ICU headers */ +#include +#include +#include +#include + +#include + +#ifndef SQLITE_CORE + #include "sqlite3ext.h" + SQLITE_EXTENSION_INIT1 +#else + #include "sqlite3.h" +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + +/* +** Version of sqlite3_free() that is always a function, never a macro. +*/ +static void xFree(void *p){ + sqlite3_free(p); +} + +/* +** Compare two UTF-8 strings for equality where the first string is +** a "LIKE" expression. Return true (1) if they are the same and +** false (0) if they are different. +*/ +static int icuLikeCompare( + const uint8_t *zPattern, /* LIKE pattern */ + const uint8_t *zString, /* The UTF-8 string to compare against */ + const UChar32 uEsc /* The escape character */ +){ + static const int MATCH_ONE = (UChar32)'_'; + static const int MATCH_ALL = (UChar32)'%'; + + int iPattern = 0; /* Current byte index in zPattern */ + int iString = 0; /* Current byte index in zString */ + + int prevEscape = 0; /* True if the previous character was uEsc */ + + while( zPattern[iPattern]!=0 ){ + + /* 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: + ** + ** 1. uPattern is an unescaped match-all character "%", + ** 2. uPattern is an unescaped match-one character "_", + ** 3. uPattern is an unescaped escape character, or + ** 4. uPattern is to be handled as an ordinary character + */ + if( !prevEscape && uPattern==MATCH_ALL ){ + /* Case 1. */ + uint8_t c; + + /* Skip any MATCH_ALL or MATCH_ONE characters that follow a + ** MATCH_ALL. For each MATCH_ONE, skip one character in the + ** test string. + */ + while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){ + if( c==MATCH_ONE ){ + if( zString[iString]==0 ) return 0; + U8_FWD_1_UNSAFE(zString, iString); + } + iPattern++; + } + + if( zPattern[iPattern]==0 ) return 1; + + while( zString[iString] ){ + if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){ + return 1; + } + U8_FWD_1_UNSAFE(zString, iString); + } + return 0; + + }else if( !prevEscape && uPattern==MATCH_ONE ){ + /* Case 2. */ + if( zString[iString]==0 ) return 0; + U8_FWD_1_UNSAFE(zString, iString); + + }else if( !prevEscape && uPattern==uEsc){ + /* Case 3. */ + prevEscape = 1; + + }else{ + /* Case 4. */ + UChar32 uString; + U8_NEXT_UNSAFE(zString, iString, uString); + uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT); + uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT); + if( uString!=uPattern ){ + return 0; + } + prevEscape = 0; + } + } + + return zString[iString]==0; +} + +/* +** Implementation of the like() SQL function. This function implements +** the build-in LIKE operator. The first argument to the function is the +** pattern and the second argument is the string. So, the SQL statements: +** +** A LIKE B +** +** is implemented as like(B, A). If there is an escape character E, +** +** A LIKE B ESCAPE E +** +** is mapped to like(B, A, E). +*/ +static void icuLikeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zA = sqlite3_value_text(argv[0]); + const unsigned char *zB = sqlite3_value_text(argv[1]); + UChar32 uEsc = 0; + + /* Limit the length of the LIKE or GLOB pattern to avoid problems + ** of deep recursion and N*N behavior in patternCompare(). + */ + if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ + sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); + return; + } + + + if( argc==3 ){ + /* The escape character string must consist of a single UTF-8 character. + ** Otherwise, return an error. + */ + int nE= sqlite3_value_bytes(argv[2]); + const unsigned char *zE = sqlite3_value_text(argv[2]); + int i = 0; + if( zE==0 ) return; + U8_NEXT(zE, i, nE, uEsc); + if( i!=nE){ + sqlite3_result_error(context, + "ESCAPE expression must be a single character", -1); + return; + } + } + + if( zA && zB ){ + sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc)); + } +} + +/* +** This function is called when an ICU function called from within +** the implementation of an SQL scalar function returns an error. +** +** The scalar function context passed as the first argument is +** loaded with an error message based on the following two args. +*/ +static void icuFunctionError( + sqlite3_context *pCtx, /* SQLite scalar function context */ + const char *zName, /* Name of ICU function that failed */ + UErrorCode e /* Error code returned by ICU function */ +){ + char zBuf[128]; + sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e)); + zBuf[127] = '\0'; + sqlite3_result_error(pCtx, zBuf, -1); +} + +/* +** Function to delete compiled regexp objects. Registered as +** a destructor function with sqlite3_set_auxdata(). +*/ +static void icuRegexpDelete(void *p){ + URegularExpression *pExpr = (URegularExpression *)p; + uregex_close(pExpr); +} + +/* +** Implementation of SQLite REGEXP operator. This scalar function takes +** two arguments. The first is a regular expression pattern to compile +** the second is a string to match against that pattern. If either +** argument is an SQL NULL, then NULL Is returned. Otherwise, the result +** is 1 if the string matches the pattern, or 0 otherwise. +** +** SQLite maps the regexp() function to the regexp() operator such +** that the following two are equivalent: +** +** zString REGEXP zPattern +** regexp(zPattern, zString) +** +** Uses the following ICU regexp APIs: +** +** uregex_open() +** uregex_matches() +** uregex_close() +*/ +static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){ + UErrorCode status = U_ZERO_ERROR; + URegularExpression *pExpr; + UBool res; + const UChar *zString = sqlite3_value_text16(apArg[1]); + + /* If the left hand side of the regexp operator is NULL, + ** then the result is also NULL. + */ + if( !zString ){ + return; + } + + pExpr = sqlite3_get_auxdata(p, 0); + if( !pExpr ){ + const UChar *zPattern = sqlite3_value_text16(apArg[0]); + if( !zPattern ){ + return; + } + pExpr = uregex_open(zPattern, -1, 0, 0, &status); + + if( U_SUCCESS(status) ){ + sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete); + }else{ + assert(!pExpr); + icuFunctionError(p, "uregex_open", status); + return; + } + } + + /* Configure the text that the regular expression operates on. */ + uregex_setText(pExpr, zString, -1, &status); + if( !U_SUCCESS(status) ){ + icuFunctionError(p, "uregex_setText", status); + return; + } + + /* Attempt the match */ + res = uregex_matches(pExpr, 0, &status); + if( !U_SUCCESS(status) ){ + icuFunctionError(p, "uregex_matches", status); + return; + } + + /* Set the text that the regular expression operates on to a NULL + ** pointer. This is not really necessary, but it is tidier than + ** leaving the regular expression object configured with an invalid + ** pointer after this function returns. + */ + uregex_setText(pExpr, 0, 0, &status); + + /* Return 1 or 0. */ + sqlite3_result_int(p, res ? 1 : 0); +} + +/* +** Implementations of scalar functions for case mapping - upper() and +** lower(). Function upper() converts its input to upper-case (ABC). +** Function lower() converts to lower-case (abc). +** +** ICU provides two types of case mapping, "general" case mapping and +** "language specific". Refer to ICU documentation for the differences +** between the two. +** +** To utilise "general" case mapping, the upper() or lower() scalar +** functions are invoked with one argument: +** +** upper('ABC') -> 'abc' +** lower('abc') -> 'ABC' +** +** To access ICU "language specific" case mapping, upper() or lower() +** should be invoked with two arguments. The second argument is the name +** of the locale to use. Passing an empty string ("") or SQL NULL value +** as the second argument is the same as invoking the 1 argument version +** of upper() or lower(). +** +** lower('I', 'en_us') -> 'i' +** lower('I', 'tr_tr') -> 'ı' (small dotless i) +** +** http://www.icu-project.org/userguide/posix.html#case_mappings +*/ +static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){ + const UChar *zInput; + UChar *zOutput; + int nInput; + int nOutput; + + UErrorCode status = U_ZERO_ERROR; + const char *zLocale = 0; + + assert(nArg==1 || nArg==2); + if( nArg==2 ){ + zLocale = (const char *)sqlite3_value_text(apArg[1]); + } + + zInput = sqlite3_value_text16(apArg[0]); + if( !zInput ){ + return; + } + nInput = sqlite3_value_bytes16(apArg[0]); + + nOutput = nInput * 2 + 2; + zOutput = sqlite3_malloc(nOutput); + if( !zOutput ){ + return; + } + + if( sqlite3_user_data(p) ){ + u_strToUpper(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status); + }else{ + u_strToLower(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status); + } + + if( !U_SUCCESS(status) ){ + icuFunctionError(p, "u_strToLower()/u_strToUpper", status); + return; + } + + sqlite3_result_text16(p, zOutput, -1, xFree); +} + +/* +** Collation sequence destructor function. The pCtx argument points to +** a UCollator structure previously allocated using ucol_open(). +*/ +static void icuCollationDel(void *pCtx){ + UCollator *p = (UCollator *)pCtx; + ucol_close(p); +} + +/* +** Collation sequence comparison function. The pCtx argument points to +** a UCollator structure previously allocated using ucol_open(). +*/ +static int icuCollationColl( + void *pCtx, + int nLeft, + const void *zLeft, + int nRight, + const void *zRight +){ + UCollationResult res; + UCollator *p = (UCollator *)pCtx; + res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2); + switch( res ){ + case UCOL_LESS: return -1; + case UCOL_GREATER: return +1; + case UCOL_EQUAL: return 0; + } + assert(!"Unexpected return value from ucol_strcoll()"); + return 0; +} + +/* +** Implementation of the scalar function icu_load_collation(). +** +** This scalar function is used to add ICU collation based collation +** types to an SQLite database connection. It is intended to be called +** as follows: +** +** SELECT icu_load_collation(, ); +** +** Where is a string containing an ICU locale identifier (i.e. +** "en_AU", "tr_TR" etc.) and is the name of the +** collation sequence to create. +*/ +static void icuLoadCollation( + sqlite3_context *p, + int nArg, + sqlite3_value **apArg +){ + sqlite3 *db = (sqlite3 *)sqlite3_user_data(p); + UErrorCode status = U_ZERO_ERROR; + const char *zLocale; /* Locale identifier - (eg. "jp_JP") */ + const char *zName; /* SQL Collation sequence name (eg. "japanese") */ + UCollator *pUCollator; /* ICU library collation object */ + int rc; /* Return code from sqlite3_create_collation_x() */ + + assert(nArg==2); + zLocale = (const char *)sqlite3_value_text(apArg[0]); + zName = (const char *)sqlite3_value_text(apArg[1]); + + if( !zLocale || !zName ){ + return; + } + + pUCollator = ucol_open(zLocale, &status); + if( !U_SUCCESS(status) ){ + icuFunctionError(p, "ucol_open", status); + return; + } + assert(p); + + rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator, + icuCollationColl, icuCollationDel + ); + if( rc!=SQLITE_OK ){ + ucol_close(pUCollator); + sqlite3_result_error(p, "Error registering collation function", -1); + } +} + +/* +** Register the ICU extension functions with database db. +*/ +int sqlite3IcuInit(sqlite3 *db){ + struct IcuScalar { + const char *zName; /* Function name */ + int nArg; /* Number of arguments */ + int enc; /* Optimal text encoding */ + void *pContext; /* sqlite3_user_data() context */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } scalars[] = { + {"regexp",-1, SQLITE_ANY, 0, icuRegexpFunc}, + + {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16}, + {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16}, + {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16}, + {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16}, + + {"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16}, + {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16}, + {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16}, + {"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16}, + + {"like", 2, SQLITE_UTF8, 0, icuLikeFunc}, + {"like", 3, SQLITE_UTF8, 0, icuLikeFunc}, + + {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation}, + }; + + int rc = SQLITE_OK; + int i; + + for(i=0; rc==SQLITE_OK && i<(sizeof(scalars)/sizeof(struct IcuScalar)); i++){ + struct IcuScalar *p = &scalars[i]; + rc = sqlite3_create_function( + db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0 + ); + } + + return rc; +} + +#if !SQLITE_CORE +int sqlite3_extension_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + SQLITE_EXTENSION_INIT2(pApi) + return sqlite3IcuInit(db); +} +#endif + +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/install.sh b/client/src/thirdparty/sqlite-3.4.2/install.sh new file mode 100644 index 0000000..e9de238 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/install.sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# 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. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# 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 $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/client/src/thirdparty/sqlite-3.4.2/libtool b/client/src/thirdparty/sqlite-3.4.2/libtool new file mode 100644 index 0000000..ef332c5 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/libtool @@ -0,0 +1,7625 @@ +#! /dev/env/DJDIR/bin/sh.exe + +# libtoolT - Provide generalized library-building support services. +# Generated automatically by (GNU ) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 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 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# 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. + +# A sed program that does not truncate output. +SED="/dev/e/djgpp/bin/sed" + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="/dev/e/djgpp/bin/sed -e 1s/^X//" + +# 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 + +# The names of the tagged configurations supported by this script. +available_tags=" CXX" + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host SCHREIBTISCH_GP: + +# Shell to use when invoking shell scripts. +SHELL="/dev/env/DJDIR/bin/sh.exe" + +# Whether or not to build shared libraries. +build_libtool_libs=no + +# Whether or not to build static libraries. +build_old_libs=yes + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=yes + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=no + +# Whether or not to optimize for fast installation. +fast_install=needless + +# The host system. +host_alias= +host=i386-pc-msdosdjgpp +host_os=msdosdjgpp + +# The build system. +build_alias= +build=i386-pc-msdosdjgpp +build_os=msdosdjgpp + +# An echo program that does not interpret backslashes. +echo="echo" + +# The archiver. +AR="ar" +AR_FLAGS="cru" + +# A C compiler. +LTCC="gcc" + +# LTCC compiler flags. +LTCFLAGS="-g -O2" + +# A language-specific compiler. +CC="gcc" + +# Is the compiler the GNU C compiler? +with_gcc=yes + +# An ERE matcher. +EGREP="grep -E" + +# The linker used to build libraries. +LD="e:/djgpp/bin/ld.exe" + +# Whether we need hard or soft links. +LN_S="ln" + +# A BSD-compatible nm program. +NM="/dev/e/djgpp/bin/nm -B" + +# A symbol stripping program +STRIP="strip" + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=file + +# Used on cygwin: DLL creation program. +DLLTOOL="dlltool" + +# Used on cygwin: object dumper. +OBJDUMP="objdump" + +# Used on cygwin: assembler. +AS="as" + +# The name of the directory that contains temporary libtool files. +objdir=.libs + +# How to create reloadable object files. +reload_flag=" -r" +reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Object file suffix (normally "o"). +objext="o" + +# Old archive suffix (normally "a"). +libext="a" + +# Shared library suffix (normally ".so"). +shrext_cmds='.so' + +# Executable file suffix (normally ""). +exeext="" + +# Additional compiler flags for building library objects. +pic_flag="" +pic_mode=default + +# What is the maximum length of a command? +max_cmd_len=12288 + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Must we lock files when doing compilation? +need_locks="no" + +# Do we need the lib prefix for modules? +need_lib_prefix=unknown + +# Do we need a version for libraries? +need_version=unknown + +# Whether dlopen is supported. +dlopen_support=unknown + +# Whether dlopen of programs is supported. +dlopen_self=unknown + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=unknown + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="" + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec="" + +# Library versioning type. +version_type=none + +# Format of library name prefix. +libname_spec="lib\$name" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="" + +# The coded name of the library, if different from the real name. +soname_spec="" + +# Commands used to build and install an old-style archive. +RANLIB="ranlib" +old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs\$old_deplibs~\$RANLIB \$oldlib" +old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib" +old_postuninstall_cmds="" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds="" + +# Commands used to build and install a shared archive. +archive_cmds="" +archive_expsym_cmds="" +postinstall_cmds="" +postuninstall_cmds="" + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds="" +module_expsym_cmds="" + +# Commands to strip libraries. +old_striplib="strip --strip-debug" +striplib="strip --strip-unneeded" + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects="" + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects="" + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps="" + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps="" + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path="" + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method="unknown" + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd="\$MAGIC_CMD" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that forces no undefined symbols. +no_undefined_flag="" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*_\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 _\\2 \\2/p'" + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'" + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/ {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/ {\"\\2\", (lt_ptr) \\&\\2},/p'" + +# This is the shared library runtime path variable. +runpath_var= + +# This is the shared library path variable. +shlibpath_var= + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=unknown + +# How to hardcode a shared library path into an executable. +hardcode_action=unsupported + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=no + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist. +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="" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="" + +# Set to yes if using DIR/libNAME during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=no + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=no + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=unsupported + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=no + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=unknown + +# Compile-time system search path for libraries +sys_lib_search_path_spec=" =e:/djgpp/bin/../lib/gcc/djgpp/4.53/ e:/djgpp/bin/../lib/gcc/ e:/djgpp/net/watt/lib /djgpp/4.53/ e:/djgpp/net/watt/lib / e:/djgpp/lib/djgpp/4.53/ e:/djgpp/lib/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../../djgpp/lib/djgpp/4.53/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../../djgpp/lib/ e:/djgpp/lib/djgpp/4.53/ e:/djgpp/lib/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../djgpp/4.53/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../" + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +# Fix the shell variable $srcfile for the compiler. +fix_srcfile_path="" + +# Set to yes if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds="" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + +# Symbols that must always be exported. +include_expsyms="" + +# ### END LIBTOOL CONFIG + +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 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 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# 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. + +basename="s,^.*/,,g" + +# 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" + +# define SED for historic ltconfig's generated by Libtool 1.3 +test -z "$SED" && SED=sed + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# 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 + setopt NO_GLOB_SUBST +fi +# Same for EGREP, and just to be sure, do LTCC as well +if test "X$EGREP" = X ; then + EGREP=egrep +fi +if test "X$LTCC" = X ; then + LTCC=${CC-gcc} +fi + +# Check that we have a working $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, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +if test -z "$max_cmd_len"; then + i=0 + testring="ABCD" + new_result= + + # 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"`$SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ + = "XX$testring") >/dev/null 2>&1 && + new_result=`expr "X$testring" : ".*" 2>&1` && + max_cmd_len="$new_result" && + test "$i" != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + testring="$testring$testring" + done + testring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + max_cmd_len=`expr $max_cmd_len \/ 2` +fi + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# 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 "$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" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# 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. +func_win32_libid () +{ + 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 + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $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_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 () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + 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 "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # 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. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + # user sometimes does CC=-gcc so we need to match that to 'gcc' + trimedcc=`echo ${CC} | $SED -e "s/${host}-//g"` + # and sometimes libtool has CC=-gcc but user does CC=gcc + extendcc=${host}-${CC} + # and sometimes libtool has CC=-gcc but user has CC=-gcc + # (Gentoo-specific hack because we always export $CHOST) + mungedcc=${CHOST-${host}}-${trimedcc} + case "$@ " in + "cc "* | " cc "* | "${host}-cc "* | " ${host}-cc "*|\ + "gcc "* | " gcc "* | "${host}-gcc "* | " ${host}-gcc "*) + tagname=CC + break ;; + "$trimedcc "* | " $trimedcc "* | "`$echo $trimedcc` "* | " `$echo $trimedcc` "*|\ + "$extendcc "* | " $extendcc "* | "`$echo $extendcc` "* | " `$echo $extendcc` "*|\ + "$mungedcc "* | " $mungedcc "* | "`$echo $mungedcc` "* | " `$echo $mungedcc` "*|\ + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # 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 + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + 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 + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + 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 have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --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 $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# 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= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # 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= + + 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) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$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,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$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. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # 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 + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + 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 "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + 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 $run ln "$srcfile" "$lockfile" 2>/dev/null; do + $show "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." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </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." + + $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 + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </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." + + $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 + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + 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 + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$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 + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + 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 + dlfiles="$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. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$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 + non_pic_objects="$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" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + 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 + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + 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 + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + 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*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$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*) + # 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 + deplibs="$deplibs -framework System" + 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 + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + 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*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # 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 + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + 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 + dlfiles="$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. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$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 + non_pic_objects="$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" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + 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. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'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\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + 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 test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$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 test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$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 + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + 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 + 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 "$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) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; 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 (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + 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 + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + 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 + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + 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 + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + 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 used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + 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. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # 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 + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$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 + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + 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. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$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 + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$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 + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + 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 + newlib_search_path="$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*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + 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 test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$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 -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 + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$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 "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$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 + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if 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 "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; 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*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + 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 "$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 module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; 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 + 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; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$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 + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$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:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; 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:"*) ;; + *) finalize_shlibpath="$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 + [\\/]*) + add_dir="$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*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$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" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + 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 "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + 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 "*) ;; + *) lib_search_path="$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 "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$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 + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + 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 + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # 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="$2" + number_minor="$3" + number_revision="$4" + # + # 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 + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + 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]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + 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]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + 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]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + 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 + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + 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 + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + 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 + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + 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 + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$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) + ;; + $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 + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "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 + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$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 "*) ;; + *) dlfiles="$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 "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-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 + deplibs="$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. + $rm conftest.c + cat > conftest.c </dev/null` + 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 "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + # It is ok to link against an archive when + # building a shared library. + if $AR -t $potlib > /dev/null 2>&1; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$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 + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$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 + newdeplibs="$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 + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e '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 "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $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 + fi + ;; + 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 is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + 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 + + + # 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 "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$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 + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$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 + 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"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$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" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$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 "$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 + realname="$2" + shift; 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 + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "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"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $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:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # 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 + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$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. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + 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~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "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" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + 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\" + 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 + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(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 "$mode" = relink; then + $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 + $show "${rm}r $gentop" + $run ${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 + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run 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 "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $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 + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${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" + # $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" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + 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 "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$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 "*) ;; + *) finalize_rpath="$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"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$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"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$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 "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # 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/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + 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*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + 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 "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + 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 + rpath="$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 + rpath="$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 "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + 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" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e '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 "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "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}\" || 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 + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + 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 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#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 +# 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 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +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; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + 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 ("getcwd failed"); + 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 ("getcwd failed"); + 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 * +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; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# 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. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# 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 variable: + 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 + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e '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 \"X\$file\" | \$Xsed -e '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 \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + 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 >> $output "\ + + # 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 $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # 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 \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + + # Make sure env LD_LIBRARY_PATH does not mess us up + if test -n \"\${LD_LIBRARY_PATH+set}\"; then + export LD_LIBRARY_PATH=\$progdir:\$LD_LIBRARY_PATH + fi +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + 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 $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + 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" + 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" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$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 + # 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 + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_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 + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$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= + 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 + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "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}\" || 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 + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; 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 "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + 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) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "X$EGREP" = X ; then + EGREP=egrep + fi + # We do not want portage's install root ($D) present. Check only for + # this if the .la is being installed. + if test "$installed" = yes && test "$D"; then + eval mynewdependency_lib=`echo "$libdir/$name" |sed -e "s:$D:/:g" -e 's:/\+:/:g'` + else + mynewdependency_lib="$libdir/$name" + fi + # Do not add duplicates + if test "$mynewdependency_lib"; then + my_little_ninja_foo_1=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"` + if test -z "$my_little_ninja_foo_1"; then + newdependency_libs="$newdependency_libs $mynewdependency_lib" + fi + fi + ;; + *) + if test "$installed" = yes; then + # Rather use S=WORKDIR if our version of portage supports it. + # This is because some ebuild (gcc) do not use $S as buildroot. + if test "$PWORKDIR"; then + S="$PWORKDIR" + fi + # We do not want portage's build root ($S) present. + my_little_ninja_foo_2=`echo $deplib |$EGREP -e "$S"` + # We do not want portage's install root ($D) present. + my_little_ninja_foo_3=`echo $deplib |$EGREP -e "$D"` + if test -n "$my_little_ninja_foo_2" && test "$S"; then + mynewdependency_lib="" + elif test -n "$my_little_ninja_foo_3" && test "$D"; then + eval mynewdependency_lib=`echo "$deplib" |sed -e "s:$D:/:g" -e 's:/\+:/:g'` + else + mynewdependency_lib="$deplib" + fi + else + mynewdependency_lib="$deplib" + fi + # Do not add duplicates + if test "$mynewdependency_lib"; then + my_little_ninja_foo_4=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"` + if test -z "$my_little_ninja_foo_4"; then + newdependency_libs="$newdependency_libs $mynewdependency_lib" + fi + fi + ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + # Do not add duplicates + if test "$installed" = yes && test "$D"; then + install_libdir=`echo "$install_libdir" |sed -e "s:$D:/:g" -e 's:/\+:/:g'` + fi + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# 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' + +# Libraries that this one depends upon. +dependency_libs='$dependency_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 + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # 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. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + 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. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$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 "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. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + 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 + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run 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 + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$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 + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run 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 + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + 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 + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo 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. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo 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. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "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) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $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" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + 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 + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # 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 + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + 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) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + 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 (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$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 + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [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 + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +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. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [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: $modename [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 + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +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: $modename [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: $modename [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: $modename [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 rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [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 + -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 + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +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: $modename [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." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# 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 +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# Libtool was configured on host SCHREIBTISCH_GP: + +# Shell to use when invoking shell scripts. +SHELL="/dev/env/DJDIR/bin/sh.exe" + +# Whether or not to build shared libraries. +build_libtool_libs=no + +# Whether or not to build static libraries. +build_old_libs=yes + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=no + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=no + +# Whether or not to optimize for fast installation. +fast_install=needless + +# The host system. +host_alias= +host=i386-pc-msdosdjgpp +host_os=msdosdjgpp + +# The build system. +build_alias= +build=i386-pc-msdosdjgpp +build_os=msdosdjgpp + +# An echo program that does not interpret backslashes. +echo="echo" + +# The archiver. +AR="ar" +AR_FLAGS="cru" + +# A C compiler. +LTCC="gcc" + +# LTCC compiler flags. +LTCFLAGS="-g -O2" + +# A language-specific compiler. +CC="gpp" + +# Is the compiler the GNU C compiler? +with_gcc=yes + +# An ERE matcher. +EGREP="grep -E" + +# The linker used to build libraries. +LD="e:/djgpp/bin/ld.exe" + +# Whether we need hard or soft links. +LN_S="ln" + +# A BSD-compatible nm program. +NM="/dev/e/djgpp/bin/nm -B" + +# A symbol stripping program +STRIP="strip" + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=file + +# Used on cygwin: DLL creation program. +DLLTOOL="dlltool" + +# Used on cygwin: object dumper. +OBJDUMP="objdump" + +# Used on cygwin: assembler. +AS="as" + +# The name of the directory that contains temporary libtool files. +objdir=.libs + +# How to create reloadable object files. +reload_flag=" -r" +reload_cmds="\$LD\$reload_flag -o \$output\$reload_objs" + +# How to pass a linker flag through the compiler. +wl="-Wl," + +# Object file suffix (normally "o"). +objext="o" + +# Old archive suffix (normally "a"). +libext="a" + +# Shared library suffix (normally ".so"). +shrext_cmds='.so' + +# Executable file suffix (normally ""). +exeext="" + +# Additional compiler flags for building library objects. +pic_flag="" +pic_mode=default + +# What is the maximum length of a command? +max_cmd_len=12288 + +# Does compiler simultaneously support -c and -o options? +compiler_c_o="yes" + +# Must we lock files when doing compilation? +need_locks="no" + +# Do we need the lib prefix for modules? +need_lib_prefix=unknown + +# Do we need a version for libraries? +need_version=unknown + +# Whether dlopen is supported. +dlopen_support=unknown + +# Whether dlopen of programs is supported. +dlopen_self=unknown + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=unknown + +# Compiler flag to prevent dynamic linking. +link_static_flag="-static" + +# Compiler flag to turn off builtin functions. +no_builtin_flag=" -fno-builtin" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="\${wl}--export-dynamic" + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec="\${wl}--whole-archive\$convenience \${wl}--no-whole-archive" + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec="" + +# Library versioning type. +version_type=none + +# Format of library name prefix. +libname_spec="lib\$name" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="" + +# The coded name of the library, if different from the real name. +soname_spec="" + +# Commands used to build and install an old-style archive. +RANLIB="ranlib" +old_archive_cmds="\$AR \$AR_FLAGS \$oldlib\$oldobjs\$old_deplibs~\$RANLIB \$oldlib" +old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$oldlib" +old_postuninstall_cmds="" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="" + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds="" + +# Commands used to build and install a shared archive. +archive_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname -o \$lib" +archive_expsym_cmds="\$CC -shared -nostdlib \$predep_objects \$libobjs \$deplibs \$postdep_objects \$compiler_flags \${wl}-soname \$wl\$soname \${wl}-retain-symbols-file \$wl\$export_symbols -o \$lib" +postinstall_cmds="" +postuninstall_cmds="" + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds="" +module_expsym_cmds="" + +# Commands to strip libraries. +old_striplib="strip --strip-debug" +striplib="strip --strip-unneeded" + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects="e:/djgpp/lib/crt0.o" + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects="" + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps="" + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps="-lstdcxx -lm -lgcc -lc -lgcc" + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path="-Le:/djgpp/bin/../lib/gcc/djgpp/4.53 -Le:/djgpp/bin/../lib/gcc -Le:/djgpp/net/watt/lib -Le:/djgpp/lib -Le:/djgpp/bin/../lib/gcc/djgpp/4.53/../../.." + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method="unknown" + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd="\$MAGIC_CMD" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="" + +# Flag that forces no undefined symbols. +no_undefined_flag="" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*_\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 _\\2 \\2/p'" + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \\(.*\\)\$/extern int \\1;/p'" + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address="sed -n -e 's/^: \\([^ ]*\\) \$/ {\\\"\\1\\\", (lt_ptr) 0},/p' -e 's/^[BCDEGRST] \\([^ ]*\\) \\([^ ]*\\)\$/ {\"\\2\", (lt_ptr) \\&\\2},/p'" + +# This is the shared library runtime path variable. +runpath_var= + +# This is the shared library path variable. +shlibpath_var= + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=unknown + +# How to hardcode a shared library path into an executable. +hardcode_action=immediate + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=no + +# Flag to hardcode $libdir into a binary during linking. +# This must work even if $libdir does not exist. +hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir" + +# 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="" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="" + +# Set to yes if using DIR/libNAME during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=no + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=no + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=unsupported + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=no + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=unknown + +# Compile-time system search path for libraries +sys_lib_search_path_spec=" =e:/djgpp/bin/../lib/gcc/djgpp/4.53/ e:/djgpp/bin/../lib/gcc/ e:/djgpp/net/watt/lib /djgpp/4.53/ e:/djgpp/net/watt/lib / e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../../djgpp/lib/djgpp/4.53/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../../djgpp/lib/ e:/djgpp/lib/djgpp/4.53/ e:/djgpp/lib/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../djgpp/4.53/ e:/djgpp/bin/../lib/gcc/djgpp/4.53/../../../" + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec="/lib /usr/lib" + +# Fix the shell variable $srcfile for the compiler. +fix_srcfile_path="" + +# Set to yes if exported symbols are required. +always_export_symbols=no + +# The commands to list exported symbols. +export_symbols_cmds="\$NM \$libobjs \$convenience | \$global_symbol_pipe | \$SED 's/.* //' | sort | uniq > \$export_symbols" + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds="" + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms="" + +# Symbols that must always be exported. +include_expsyms="" + +# ### END LIBTOOL TAG CONFIG: CXX + diff --git a/client/src/thirdparty/sqlite-3.4.2/ltmain.sh b/client/src/thirdparty/sqlite-3.4.2/ltmain.sh new file mode 100644 index 0000000..8f7a6ac --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/ltmain.sh @@ -0,0 +1,6971 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit , 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 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# 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. + +basename="s,^.*/,,g" + +# 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" + +# define SED for historic ltconfig's generated by Libtool 1.3 +test -z "$SED" && SED=sed + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# 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 + setopt NO_GLOB_SUBST +fi +# Same for EGREP, and just to be sure, do LTCC as well +if test "X$EGREP" = X ; then + EGREP=egrep +fi +if test "X$LTCC" = X ; then + LTCC=${CC-gcc} +fi + +# Check that we have a working $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, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +if test -z "$max_cmd_len"; then + i=0 + testring="ABCD" + new_result= + + # 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"`$SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ + = "XX$testring") >/dev/null 2>&1 && + new_result=`expr "X$testring" : ".*" 2>&1` && + max_cmd_len="$new_result" && + test "$i" != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + testring="$testring$testring" + done + testring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + max_cmd_len=`expr $max_cmd_len \/ 2` +fi + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# 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 "$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" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# 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. +func_win32_libid () +{ + 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 + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $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_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 () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + 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 "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # 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. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + # user sometimes does CC=-gcc so we need to match that to 'gcc' + trimedcc=`echo ${CC} | $SED -e "s/${host}-//g"` + # and sometimes libtool has CC=-gcc but user does CC=gcc + extendcc=${host}-${CC} + # and sometimes libtool has CC=-gcc but user has CC=-gcc + # (Gentoo-specific hack because we always export $CHOST) + mungedcc=${CHOST-${host}}-${trimedcc} + case "$@ " in + "cc "* | " cc "* | "${host}-cc "* | " ${host}-cc "*|\ + "gcc "* | " gcc "* | "${host}-gcc "* | " ${host}-gcc "*) + tagname=CC + break ;; + "$trimedcc "* | " $trimedcc "* | "`$echo $trimedcc` "* | " `$echo $trimedcc` "*|\ + "$extendcc "* | " $extendcc "* | "`$echo $extendcc` "* | " `$echo $extendcc` "*|\ + "$mungedcc "* | " $mungedcc "* | "`$echo $mungedcc` "* | " `$echo $mungedcc` "*|\ + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # 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 + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + 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 + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + 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 have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --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 $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# 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= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # 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= + + 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) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$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,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$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. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # 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 + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + 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 "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + 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 $run ln "$srcfile" "$lockfile" 2>/dev/null; do + $show "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." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </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." + + $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 + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </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." + + $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 + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + 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 + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$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 + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + 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 + dlfiles="$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. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$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 + non_pic_objects="$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" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + 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 + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + 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 + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + 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*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$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*) + # 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 + deplibs="$deplibs -framework System" + 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 + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + 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*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # 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 + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + 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 + dlfiles="$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. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$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 + non_pic_objects="$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" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + 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. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'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\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + 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 test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$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 test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$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 + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + 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 + 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 "$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) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; 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 (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + 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 + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + 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 + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + 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 + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + 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 used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + 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. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # 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 + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$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 + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + 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. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$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 + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$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 + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + 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 + newlib_search_path="$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*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + 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 test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$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 -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 + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$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 "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$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 + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if 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 "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; 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*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + 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 "$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 module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; 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 + 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; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$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 + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$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:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; 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:"*) ;; + *) finalize_shlibpath="$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 + [\\/]*) + add_dir="$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*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$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" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + 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 "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + 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 "*) ;; + *) lib_search_path="$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 "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$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 + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + 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 + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # 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="$2" + number_minor="$3" + number_revision="$4" + # + # 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 + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + 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]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + 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]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + 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]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + 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 + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + 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 + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + 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 + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + 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 + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$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) + ;; + $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 + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "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 + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$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 "*) ;; + *) dlfiles="$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 "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-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 + deplibs="$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. + $rm conftest.c + cat > conftest.c </dev/null` + 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 "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + # It is ok to link against an archive when + # building a shared library. + if $AR -t $potlib > /dev/null 2>&1; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$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 + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$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 + newdeplibs="$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 + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e '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 "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $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 + fi + ;; + 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 is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + 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 + + + # 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 "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$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 + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$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 + 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"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$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" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$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 "$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 + realname="$2" + shift; 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 + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "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"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $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:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # 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 + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$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. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + 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~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "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" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + 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\" + 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 + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(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 "$mode" = relink; then + $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 + $show "${rm}r $gentop" + $run ${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 + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run 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 "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $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 + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${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" + # $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" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + 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 "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$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 "*) ;; + *) finalize_rpath="$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"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$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"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$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 "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # 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/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + 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*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + 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 "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + 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 + rpath="$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 + rpath="$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 "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + 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" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e '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 "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "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}\" || 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 + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + 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 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#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 +# 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 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +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; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + 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 ("getcwd failed"); + 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 ("getcwd failed"); + 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 * +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; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# 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. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# 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 variable: + 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 + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e '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 \"X\$file\" | \$Xsed -e '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 \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + 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 >> $output "\ + + # 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 $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # 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 \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + + # Make sure env LD_LIBRARY_PATH does not mess us up + if test -n \"\${LD_LIBRARY_PATH+set}\"; then + export LD_LIBRARY_PATH=\$progdir:\$LD_LIBRARY_PATH + fi +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + 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 $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + 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" + 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" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$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 + # 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 + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_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 + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$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= + 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 + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "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}\" || 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 + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; 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 "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + 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) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "X$EGREP" = X ; then + EGREP=egrep + fi + # We do not want portage's install root ($D) present. Check only for + # this if the .la is being installed. + if test "$installed" = yes && test "$D"; then + eval mynewdependency_lib=`echo "$libdir/$name" |sed -e "s:$D:/:g" -e 's:/\+:/:g'` + else + mynewdependency_lib="$libdir/$name" + fi + # Do not add duplicates + if test "$mynewdependency_lib"; then + my_little_ninja_foo_1=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"` + if test -z "$my_little_ninja_foo_1"; then + newdependency_libs="$newdependency_libs $mynewdependency_lib" + fi + fi + ;; + *) + if test "$installed" = yes; then + # Rather use S=WORKDIR if our version of portage supports it. + # This is because some ebuild (gcc) do not use $S as buildroot. + if test "$PWORKDIR"; then + S="$PWORKDIR" + fi + # We do not want portage's build root ($S) present. + my_little_ninja_foo_2=`echo $deplib |$EGREP -e "$S"` + # We do not want portage's install root ($D) present. + my_little_ninja_foo_3=`echo $deplib |$EGREP -e "$D"` + if test -n "$my_little_ninja_foo_2" && test "$S"; then + mynewdependency_lib="" + elif test -n "$my_little_ninja_foo_3" && test "$D"; then + eval mynewdependency_lib=`echo "$deplib" |sed -e "s:$D:/:g" -e 's:/\+:/:g'` + else + mynewdependency_lib="$deplib" + fi + else + mynewdependency_lib="$deplib" + fi + # Do not add duplicates + if test "$mynewdependency_lib"; then + my_little_ninja_foo_4=`echo $newdependency_libs |$EGREP -e "$mynewdependency_lib"` + if test -z "$my_little_ninja_foo_4"; then + newdependency_libs="$newdependency_libs $mynewdependency_lib" + fi + fi + ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + # Do not add duplicates + if test "$installed" = yes && test "$D"; then + install_libdir=`echo "$install_libdir" |sed -e "s:$D:/:g" -e 's:/\+:/:g'` + fi + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# 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' + +# Libraries that this one depends upon. +dependency_libs='$dependency_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 + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # 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. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + 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. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$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 "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. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + 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 + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run 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 + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$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 + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run 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 + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + 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 + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo 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. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo 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. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "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) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $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" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + 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 + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # 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 + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + 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) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + 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 (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$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 + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [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 + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +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. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [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: $modename [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 + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +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: $modename [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: $modename [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: $modename [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 rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [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 + -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 + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +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: $modename [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." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# 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 +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/client/src/thirdparty/sqlite-3.4.2/main.mk b/client/src/thirdparty/sqlite-3.4.2/main.mk new file mode 100644 index 0000000..5b1fe53 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/main.mk @@ -0,0 +1,486 @@ +############################################################################### +# 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 + +# Object files for the SQLite library. +# +LIBOBJ+= alter.o analyze.o attach.o auth.o btmutex.o btree.o build.o \ + callback.o complete.o date.o delete.o \ + expr.o fault.o func.o hash.o insert.o journal.o loadext.o \ + main.o malloc.o mem1.o mem2.o mem3.o mem4.o mutex.o mutex_os2.o \ + mutex_unix.o mutex_w32.o \ + opcodes.o os.o os_os2.o os_unix.o os_win.o \ + pager.o parse.o pragma.o prepare.o printf.o random.o \ + select.o table.o $(TCLOBJ) tokenize.o trigger.o \ + update.o util.o vacuum.o \ + vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbefifo.o vdbemem.o \ + where.o utf.o legacy.o vtab.o + +EXTOBJ = icu.o +EXTOBJ += fts1.o \ + fts1_hash.o \ + fts1_tokenizer1.o \ + fts1_porter.o +EXTOBJ += fts2.o \ + fts2_hash.o \ + fts2_icu.o \ + fts2_porter.o \ + fts2_tokenizer.o \ + fts2_tokenizer1.o +EXTOBJ += fts3.o \ + fts3_hash.o \ + fts3_icu.o \ + fts3_porter.o \ + fts3_tokenizer.o \ + fts3_tokenizer1.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/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/date.c \ + $(TOP)/src/delete.c \ + $(TOP)/src/expr.c \ + $(TOP)/src/fault.c \ + $(TOP)/src/func.c \ + $(TOP)/src/hash.c \ + $(TOP)/src/hash.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/mem1.c \ + $(TOP)/src/mem2.c \ + $(TOP)/src/mem3.c \ + $(TOP)/src/mem4.c \ + $(TOP)/src/mutex.c \ + $(TOP)/src/mutex.h \ + $(TOP)/src/mutex_os2.c \ + $(TOP)/src/mutex_unix.c \ + $(TOP)/src/mutex_w32.c \ + $(TOP)/src/os.c \ + $(TOP)/src/os.h \ + $(TOP)/src/os_common.h \ + $(TOP)/src/os_os2.c \ + $(TOP)/src/os_unix.c \ + $(TOP)/src/os_win.c \ + $(TOP)/src/pager.c \ + $(TOP)/src/pager.h \ + $(TOP)/src/parse.y \ + $(TOP)/src/pragma.c \ + $(TOP)/src/prepare.c \ + $(TOP)/src/printf.c \ + $(TOP)/src/random.c \ + $(TOP)/src/select.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/vdbefifo.c \ + $(TOP)/src/vdbemem.c \ + $(TOP)/src/vdbeInt.h \ + $(TOP)/src/vtab.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_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/icu.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_btree.c \ + $(TOP)/src/test_config.c \ + $(TOP)/src/test_devsym.c \ + $(TOP)/src/test_hexio.c \ + $(TOP)/src/test_malloc.c \ + $(TOP)/src/test_md5.c \ + $(TOP)/src/test_onefile.c \ + $(TOP)/src/test_schema.c \ + $(TOP)/src/test_server.c \ + $(TOP)/src/test_tclvar.c \ + $(TOP)/src/test_thread.c \ + +#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c +#TESTSRC += $(TOP)/ext/fts3/fts3_tokenizer.c + +TESTSRC2 = \ + $(TOP)/src/attach.c $(TOP)/src/btree.c $(TOP)/src/build.c $(TOP)/src/date.c \ + $(TOP)/src/expr.c $(TOP)/src/func.c $(TOP)/src/insert.c $(TOP)/src/os.c \ + $(TOP)/src/os_os2.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/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 + +# Header files used by all library source files. +# +HDR = \ + $(TOP)/src/btree.h \ + $(TOP)/src/btreeInt.h \ + $(TOP)/src/hash.h \ + keywordhash.h \ + $(TOP)/src/mutex.h \ + opcodes.h \ + $(TOP)/src/os.h \ + $(TOP)/src/os_common.h \ + $(TOP)/src/pager.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_hash.h \ + $(TOP)/ext/fts3/fts3_tokenizer.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 + +sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h + $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) \ + $(TOP)/src/shell.c \ + libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) + +objects: $(LIBOBJ_ORIG) + +# 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)/tool/lempar.c + $(BCC) -o lemon $(TOP)/tool/lemon.c + cp $(TOP)/tool/lempar.c . + +# Rules to build individual *.o files from files in the src directory. +# +%.o: %.c $(HDR) + $(TCCX) -c $< + +# Rules to build individual *.o files from generated *.c files. This +# applies to: +# +# parse.o +# opcodes.o +# +%.o: $(TOP)/src/%.c $(HDR) + $(TCCX) -c $< + +tclsqlite.o: $(TOP)/src/tclsqlite.c $(HDR) + $(TCCX) $(TCL_FLAGS) -c $(TOP)/src/tclsqlite.c + + + +# Rules to build opcodes.c and opcodes.h +# +opcodes.c: opcodes.h $(TOP)/mkopcodec.awk + sort -n -b -k 3 opcodes.h | $(NAWK) -f $(TOP)/mkopcodec.awk >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) -DSQLITE_CORE -c $(TOP)/ext/icu/icu.c + +fts2.o: $(TOP)/ext/fts2/fts2.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2.c + +fts2_hash.o: $(TOP)/ext/fts2/fts2_hash.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_hash.c + +fts2_icu.o: $(TOP)/ext/fts2/fts2_icu.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_icu.c + +fts2_porter.o: $(TOP)/ext/fts2/fts2_porter.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_porter.c + +fts2_tokenizer.o: $(TOP)/ext/fts2/fts2_tokenizer.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer.c + +fts2_tokenizer1.o: $(TOP)/ext/fts2/fts2_tokenizer1.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts2/fts2_tokenizer1.c + +fts3.o: $(TOP)/ext/fts3/fts3.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3.c + +fts3_hash.o: $(TOP)/ext/fts3/fts3_hash.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_hash.c + +fts3_icu.o: $(TOP)/ext/fts3/fts3_icu.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_icu.c + +fts3_porter.o: $(TOP)/ext/fts3/fts3_porter.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_porter.c + +fts3_tokenizer.o: $(TOP)/ext/fts3/fts3_tokenizer.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer.c + +fts3_tokenizer1.o: $(TOP)/ext/fts3/fts3_tokenizer1.c $(HDR) $(EXTHDR) + $(TCCX) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_tokenizer1.c + + +# Rules for building test programs and for running tests +# +tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a + $(TCCX) $(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 + +test: testfixture$(EXE) sqlite3$(EXE) + ./testfixture$(EXE) $(TOP)/test/quick.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 + + +# Standard install and cleanup targets +# +install: sqlite3 libsqlite3.a sqlite3.h + mv sqlite3 /usr/bin + mv libsqlite3.a /usr/lib + mv sqlite3.h /usr/include + +clean: + rm -f *.o sqlite3 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 tsrc target_source + rm -f testloadext.dll libtestloadext.so + rm -f sqlite3.c fts?amal.c diff --git a/client/src/thirdparty/sqlite-3.4.2/mkdll.sh b/client/src/thirdparty/sqlite-3.4.2/mkdll.sh new file mode 100644 index 0000000..ed1e741 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/mkdll.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# +# This script is used to compile SQLite into a DLL. +# +# Two separate DLLs are generated. "sqlite3.dll" is the core +# library. "tclsqlite3.dll" contains the TCL bindings and is the +# library that is loaded into TCL in order to run SQLite. +# +make sqlite3.c +PATH=$PATH:/opt/mingw/bin +TCLDIR=/home/drh/tcltk/846/win/846win +TCLSTUBLIB=$TCLDIR/libtcl84stub.a +OPTS='-DUSE_TCL_STUBS=1 -DSQLITE_THREADSAFE=1 -DBUILD_sqlite=1 -DOS_WIN=1' +OPTS="$OPTS -DSQLITE_ENABLE_FTS3=1" +CC="i386-mingw32msvc-gcc -Os $OPTS -Itsrc -I$TCLDIR" +NM="i386-mingw32msvc-nm" +CMD="$CC -c sqlite3.c" +echo $CMD +$CMD +CMD="$CC -c tclsqlite3.c" +echo $CMD +$CMD +echo 'EXPORTS' >tclsqlite3.def +$NM tclsqlite3.o | grep ' T ' >temp1 +grep '_Init$' temp1 >temp2 +grep '_SafeInit$' temp1 >>temp2 +grep ' T _sqlite3_' temp1 >>temp2 +echo 'EXPORTS' >tclsqlite3.def +sed 's/^.* T _//' temp2 | sort | uniq >>tclsqlite3.def +i386-mingw32msvc-dllwrap \ + --def tclsqlite3.def -v --export-all \ + --driver-name i386-mingw32msvc-gcc \ + --dlltool-name i386-mingw32msvc-dlltool \ + --as i386-mingw32msvc-as \ + --target i386-mingw32 \ + -dllname tclsqlite3.dll -lmsvcrt tclsqlite3.o $TCLSTUBLIB +$NM sqlite3.o | grep ' T ' >temp1 +echo 'EXPORTS' >sqlite3.def +grep ' _sqlite3_' temp1 | sed 's/^.* _//' >>sqlite3.def +i386-mingw32msvc-dllwrap \ + --def sqlite3.def -v --export-all \ + --driver-name i386-mingw32msvc-gcc \ + --dlltool-name i386-mingw32msvc-dlltool \ + --as i386-mingw32msvc-as \ + --target i386-mingw32 \ + -dllname sqlite3.dll -lmsvcrt sqlite3.o diff --git a/client/src/thirdparty/sqlite-3.4.2/mkextu.sh b/client/src/thirdparty/sqlite-3.4.2/mkextu.sh new file mode 100644 index 0000000..1d96897 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/mkextu.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# This script is used to compile SQLite into a shared library on Linux. +# +# Two separate shared libraries are generated. "sqlite3.so" is the core +# library. "tclsqlite3.so" contains the TCL bindings and is the +# library that is loaded into TCL in order to run SQLite. +# +CFLAGS=-O2 -Wall +make fts2amal.c +echo gcc $CFLAGS -shared fts2amal.c -o fts2.so +gcc $CFLAGS -shared fts2amal.c -o fts2.so +strip fts2.so diff --git a/client/src/thirdparty/sqlite-3.4.2/mkextw.sh b/client/src/thirdparty/sqlite-3.4.2/mkextw.sh new file mode 100644 index 0000000..3332f91 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/mkextw.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# This script is used to compile SQLite extensions into DLLs. +# +make fts2amal.c +PATH=$PATH:/opt/mingw/bin +OPTS='-DTHREADSAFE=1 -DBUILD_sqlite=1 -DOS_WIN=1' +CC="i386-mingw32msvc-gcc -O2 $OPTS -Itsrc" +NM="i386-mingw32msvc-nm" +CMD="$CC -c fts2amal.c" +echo $CMD +$CMD +echo 'EXPORTS' >fts2.def +echo 'sqlite3_extension_init' >>fts2.def +i386-mingw32msvc-dllwrap \ + --def fts2.def -v --export-all \ + --driver-name i386-mingw32msvc-gcc \ + --dlltool-name i386-mingw32msvc-dlltool \ + --as i386-mingw32msvc-as \ + --target i386-mingw32 \ + -dllname fts2.dll -lmsvcrt fts2amal.o +zip fts2dll.zip fts2.dll fts2.def diff --git a/client/src/thirdparty/sqlite-3.4.2/mkopcodc.awk b/client/src/thirdparty/sqlite-3.4.2/mkopcodc.awk new file mode 100644 index 0000000..ec80953 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/mkopcodc.awk @@ -0,0 +1,31 @@ +#!/usr/bin/awk -f +# +# This AWK script scans the opcodes.h file (which is itself generated by +# another awk script) and uses the information gleaned to create the +# opcodes.c source file. +# +# Opcodes.c contains strings which are the symbolic names for the various +# opcodes used by the VDBE. These strings are used when disassembling a +# VDBE program during tracing or as a result of the EXPLAIN keyword. +# +BEGIN { + print "/* Automatically generated. Do not edit */" + print "/* See the mkopcodec.awk script for details. */" + printf "#if !defined(SQLITE_OMIT_EXPLAIN)" + printf " || !defined(NDEBUG)" + printf " || defined(VDBE_PROFILE)" + print " || defined(SQLITE_DEBUG)" + print "const char *sqlite3OpcodeName(int i){" + print " static const char *const azName[] = { \"?\"," +} +/define OP_/ { + sub("OP_","",$2) + i++ + printf " /* %3d */ \"%s\",\n", $3, $2 +} +END { + print " };" + print " return azName[i];" + print "}" + print "#endif" +} diff --git a/client/src/thirdparty/sqlite-3.4.2/mkopcodec.awk b/client/src/thirdparty/sqlite-3.4.2/mkopcodec.awk new file mode 100644 index 0000000..ec80953 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/mkopcodec.awk @@ -0,0 +1,31 @@ +#!/usr/bin/awk -f +# +# This AWK script scans the opcodes.h file (which is itself generated by +# another awk script) and uses the information gleaned to create the +# opcodes.c source file. +# +# Opcodes.c contains strings which are the symbolic names for the various +# opcodes used by the VDBE. These strings are used when disassembling a +# VDBE program during tracing or as a result of the EXPLAIN keyword. +# +BEGIN { + print "/* Automatically generated. Do not edit */" + print "/* See the mkopcodec.awk script for details. */" + printf "#if !defined(SQLITE_OMIT_EXPLAIN)" + printf " || !defined(NDEBUG)" + printf " || defined(VDBE_PROFILE)" + print " || defined(SQLITE_DEBUG)" + print "const char *sqlite3OpcodeName(int i){" + print " static const char *const azName[] = { \"?\"," +} +/define OP_/ { + sub("OP_","",$2) + i++ + printf " /* %3d */ \"%s\",\n", $3, $2 +} +END { + print " };" + print " return azName[i];" + print "}" + print "#endif" +} diff --git a/client/src/thirdparty/sqlite-3.4.2/mkopcodeh.awk b/client/src/thirdparty/sqlite-3.4.2/mkopcodeh.awk new file mode 100644 index 0000000..796a7af --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/mkopcodeh.awk @@ -0,0 +1,157 @@ +#!/usr/bin/awk -f +# +# Generate the file opcodes.h. +# +# This AWK script scans a concatenation of the parse.h output file from the +# parser and the vdbe.c source file in order to generate the opcodes numbers +# for all opcodes. +# +# The lines of the vdbe.c that we are interested in are of the form: +# +# case OP_aaaa: /* same as TK_bbbbb */ +# +# The TK_ comment is optional. If it is present, then the value assigned to +# the OP_ is the same as the TK_ value. If missing, the OP_ value is assigned +# a small integer that is different from every other OP_ value. +# +# We go to the trouble of making some OP_ values the same as TK_ values +# as an optimization. During parsing, things like expression operators +# are coded with TK_ values such as TK_ADD, TK_DIVIDE, and so forth. Later +# during code generation, we need to generate corresponding opcodes like +# OP_Add and OP_Divide. By making TK_ADD==OP_Add and TK_DIVIDE==OP_Divide, +# code to translate from one to the other is avoided. This makes the +# code generator run (infinitesimally) faster and more importantly it makes +# the library footprint smaller. +# +# This script also scans for lines of the form: +# +# case OP_aaaa: /* no-push */ +# +# When the no-push comment is found on an opcode, it means that that +# opcode does not leave a result on the stack. By identifying which +# opcodes leave results on the stack it is possible to determine a +# much smaller upper bound on the size of the stack. This allows +# a smaller stack to be allocated, which is important to embedded +# systems with limited memory space. This script generates a series +# of "NOPUSH_MASK" defines that contain bitmaps of opcodes that leave +# results on the stack. The NOPUSH_MASK defines are used in vdbeaux.c +# to help determine the maximum stack size. +# + + +# Remember the TK_ values from the parse.h file +/^#define TK_/ { + tk[$2] = 0+$3 +} + +# Scan for "case OP_aaaa:" lines in the vdbe.c file +/^case OP_/ { + name = $2 + sub(/:/,"",name) + sub("\r","",name) + op[name] = -1 + jump[name] = 0 + out2_prerelease[name] = 0 + in1[name] = 0 + in2[name] = 0 + in3[name] = 0 + out3[name] = 0 + for(i=3; imax ) max = op[name] + printf "#define %-25s %15d", name, op[name] + if( sameas[op[name]] ) { + printf " /* same as %-12s*/", sameas[op[name]] + } + printf "\n" + + } + seenUnused = 0; + for(i=1; i $HOME/.rpmmacros +echo "%_topdir %{HOME}/rpm" >> $HOME/.rpmmacros +mkdir $HOME/rpm +mkdir $HOME/rpm/BUILD +mkdir $HOME/rpm/SOURCES +mkdir $HOME/rpm/RPMS +mkdir $HOME/rpm/SRPMS +mkdir $HOME/rpm/SPECS + +# create the spec file from the template +sed s/SQLITE_VERSION/$VERS/g $srcdir/spec.template > $HOME/rpm/SPECS/sqlite.spec + +# copy the source tarball to the rpm directory +cp doc/sqlite-$VERS.tar.gz $HOME/rpm/SOURCES/. + +# build all the rpms +rpm -ba $HOME/rpm/SPECS/sqlite.spec >& rpm-$vers.log + +# copy the RPMs into the build directory. +mv $HOME/rpm/RPMS/i386/sqlite*-$vers*.rpm doc +mv $HOME/rpm/SRPMS/sqlite-$vers*.rpm doc + +# Build the website +# +#cp $srcdir/../historical/* doc +#make doc +#cd doc +#chmod 644 *.gz diff --git a/client/src/thirdparty/sqlite-3.4.2/publish_osx.sh b/client/src/thirdparty/sqlite-3.4.2/publish_osx.sh new file mode 100644 index 0000000..508b623 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/publish_osx.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This script is used to compile SQLite and package everything up +# so that it is ready to move to the SQLite website. +# + +# Set srcdir to the name of the directory that contains the publish.sh +# script. +# +srcdir=`echo "$0" | sed 's%\(^.*\)/[^/][^/]*$%\1%'` + +# Get the makefile. +# +cp $srcdir/Makefile.linux-gcc ./Makefile +chmod +x $srcdir/install-sh + +# Get the current version number - needed to help build filenames +# +VERS=`cat $srcdir/VERSION` +VERSW=`sed 's/\./_/g' $srcdir/VERSION` +echo "VERSIONS: $VERS $VERSW" + +# Start by building an sqlite shell for linux. +# +make clean +make sqlite3.c +CFLAGS="-Os -DSQLITE_ENABLE_FTS3=1 -DSQLITE_THREADSAFE=0" +NAME=sqlite3-$VERS-osx-x86.bin +echo '***** '"COMPILING $NAME..." +gcc $CFLAGS -Itsrc sqlite3.c tsrc/shell.c -o $NAME -ldl +strip $NAME +chmod 644 $NAME +gzip $NAME +mkdir -p doc +mv $NAME.gz doc diff --git a/client/src/thirdparty/sqlite-3.4.2/spec.template b/client/src/thirdparty/sqlite-3.4.2/spec.template new file mode 100644 index 0000000..24c5eae --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/spec.template @@ -0,0 +1,62 @@ +%define name sqlite +%define version SQLITE_VERSION +%define release 1 + +Name: %{name} +Summary: SQLite is a C library that implements an embeddable SQL database engine +Version: %{version} +Release: %{release} +Source: %{name}-%{version}.tar.gz +Group: System/Libraries +URL: http://www.hwaci.com/sw/sqlite/ +License: Public Domain +BuildRoot: %{_tmppath}/%{name}-%{version}-root + +%description +SQLite is a C library that implements an embeddable SQL database engine. +Programs that link with the SQLite library can have SQL database access +without running a separate RDBMS process. The distribution comes with a +standalone command-line access program (sqlite) that can be used to +administer an SQLite database and which serves as an example of how to +use the SQLite library. + +%package -n %{name}-devel +Summary: Header files and libraries for developing apps which will use sqlite +Group: Development/C +Requires: %{name} = %{version}-%{release} + +%description -n %{name}-devel +The sqlite-devel package contains the header files and libraries needed +to develop programs that use the sqlite database library. + +%prep +%setup -q -n %{name} + +%build +CFLAGS="%optflags -DNDEBUG=1" CXXFLAGS="%optflags -DNDEBUG=1" ./configure --prefix=%{_prefix} + +make +make doc + +%install +install -d $RPM_BUILD_ROOT/%{_prefix} +install -d $RPM_BUILD_ROOT/%{_prefix}/bin +install -d $RPM_BUILD_ROOT/%{_prefix}/include +install -d $RPM_BUILD_ROOT/%{_prefix}/lib +make install prefix=$RPM_BUILD_ROOT/%{_prefix} + +%clean +rm -fr $RPM_BUILD_ROOT + +%files +%defattr(-, root, root) +%{_libdir}/*.so* +%{_bindir}/* + +%files -n %{name}-devel +%defattr(-, root, root) +%{_libdir}/pkgconfig/sqlite3.pc +%{_libdir}/*.a +%{_libdir}/*.la +%{_includedir}/* +%doc doc/* diff --git a/client/src/thirdparty/sqlite-3.4.2/sqlite.pc.in b/client/src/thirdparty/sqlite-3.4.2/sqlite.pc.in new file mode 100644 index 0000000..16ed41c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/sqlite.pc.in @@ -0,0 +1,12 @@ +# Package Information for pkg-config + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: SQLite +Description: SQL database engine +Version: @VERSION@ +Libs: -L${libdir} -lsqlite +Cflags: -I${includedir} diff --git a/client/src/thirdparty/sqlite-3.4.2/sqlite3.1 b/client/src/thirdparty/sqlite-3.4.2/sqlite3.1 new file mode 100644 index 0000000..785995b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/sqlite3.1 @@ -0,0 +1,229 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH SQLITE3 1 "Mon Apr 15 23:49:17 2002" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +.B sqlite3 +\- A command line interface for SQLite version 3 + +.SH SYNOPSIS +.B sqlite3 +.RI [ options ] +.RI [ databasefile ] +.RI [ SQL ] + +.SH SUMMARY +.PP +.B sqlite3 +is a terminal-based front-end to the SQLite library that can evaluate +queries interactively and display the results in multiple formats. +.B sqlite3 +can also be used within shell scripts and other applications to provide +batch processing features. + +.SH DESCRIPTION +To start a +.B sqlite3 +interactive session, invoke the +.B sqlite3 +command and optionally provide the name of a database file. If the +database file does not exist, it will be created. If the database file +does exist, it will be opened. + +For example, to create a new database file named "mydata.db", create +a table named "memos" and insert a couple of records into that table: +.sp +$ +.B sqlite3 mydata.db +.br +SQLite version 3.1.3 +.br +Enter ".help" for instructions +.br +sqlite> +.B create table memos(text, priority INTEGER); +.br +sqlite> +.B insert into memos values('deliver project description', 10); +.br +sqlite> +.B insert into memos values('lunch with Christine', 100); +.br +sqlite> +.B select * from memos; +.br +deliver project description|10 +.br +lunch with Christine|100 +.br +sqlite> +.sp + +If no database name is supplied, the ATTACH sql command can be used +to attach to existing or create new database files. ATTACH can also +be used to attach to multiple databases within the same interactive +session. This is useful for migrating data between databases, +possibly changing the schema along the way. + +Optionally, a SQL statement or set of SQL statements can be supplied as +a single argument. Multiple statements should be separated by +semi-colons. + +For example: +.sp +$ +.B sqlite3 -line mydata.db 'select * from memos where priority > 20;' +.br + text = lunch with Christine +.br +priority = 100 +.br +.sp + +.SS SQLITE META-COMMANDS +.PP +The interactive interpreter offers a set of meta-commands that can be +used to control the output format, examine the currently attached +database files, or perform administrative operations upon the +attached databases (such as rebuilding indices). Meta-commands are +always prefixed with a dot (.). + +A list of available meta-commands can be viewed at any time by issuing +the '.help' command. For example: +.sp +sqlite> +.B .help +.nf +.cc | +.databases List names and files of attached databases +.dump ?TABLE? ... Dump the database in an SQL text format +.echo ON|OFF Turn command echo on or off +.exit Exit this program +.explain ON|OFF Turn output mode suitable for EXPLAIN on or off. +.header(s) ON|OFF Turn display of headers on or off +.help Show this message +.import FILE TABLE Import data from FILE into TABLE +.indices TABLE Show names of all indices on TABLE +.mode MODE ?TABLE? Set output mode where MODE is one of: + csv Comma-separated values + column Left-aligned columns. (See .width) + html HTML code + insert SQL insert statements for TABLE + line One value per line + list Values delimited by .separator string + tabs Tab-separated values + tcl TCL list elements +.nullvalue STRING Print STRING in place of NULL values +.output FILENAME Send output to FILENAME +.output stdout Send output to the screen +.prompt MAIN CONTINUE Replace the standard prompts +.quit Exit this program +.read FILENAME Execute SQL in FILENAME +.schema ?TABLE? Show the CREATE statements +.separator STRING Change separator used by output mode and .import +.show Show the current values for various settings +.tables ?PATTERN? List names of tables matching a LIKE pattern +.timeout MS Try opening locked tables for MS milliseconds +.width NUM NUM ... Set column widths for "column" mode +sqlite> +|cc . +.sp +.fi + +.SH OPTIONS +.B sqlite3 +has the following options: +.TP +.BI \-init\ file +Read and execute commands from +.I file +, which can contain a mix of SQL statements and meta-commands. +.TP +.B \-echo +Print commands before execution. +.TP +.B \-[no]header +Turn headers on or off. +.TP +.B \-column +Query results will be displayed in a table like form, using +whitespace characters to separate the columns and align the +output. +.TP +.B \-html +Query results will be output as simple HTML tables. +.TP +.B \-line +Query results will be displayed with one value per line, rows +separated by a blank line. Designed to be easily parsed by +scripts or other programs +.TP +.B \-list +Query results will be displayed with the separator (|, by default) +character between each field value. The default. +.TP +.BI \-separator\ separator +Set output field separator. Default is '|'. +.TP +.BI \-nullvalue\ string +Set string used to represent NULL values. Default is '' +(empty string). +.TP +.B \-version +Show SQLite version. +.TP +.B \-help +Show help on options and exit. + + +.SH INIT FILE +.B sqlite3 +reads an initialization file to set the configuration of the +interactive environment. Throughout initialization, any previously +specified setting can be overridden. The sequence of initialization is +as follows: + +o The default configuration is established as follows: + +.sp +.nf +.cc | +mode = LIST +separator = "|" +main prompt = "sqlite> " +continue prompt = " ...> " +|cc . +.sp +.fi + +o If the file +.B ~/.sqliterc +exists, it is processed first. +can be found in the user's home directory, it is +read and processed. It should generally only contain meta-commands. + +o If the -init option is present, the specified file is processed. + +o All other command line options are processed. + +.SH SEE ALSO +http://www.sqlite.org/ +.br +The sqlite-doc package +.SH AUTHOR +This manual page was originally written by Andreas Rottmann +, for the Debian GNU/Linux system (but may be used +by others). It was subsequently revised by Bill Bumgarner . diff --git a/client/src/thirdparty/sqlite-3.4.2/sqlite3.pc b/client/src/thirdparty/sqlite-3.4.2/sqlite3.pc new file mode 100644 index 0000000..9eea007 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/sqlite3.pc @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=/dev/env/DJDIR +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: SQLite +Description: SQL database engine +Version: 3.5 +Libs: -L${libdir} -lsqlite3 +Libs.private: -lpthread +Cflags: -I${includedir} diff --git a/client/src/thirdparty/sqlite-3.4.2/sqlite3.pc.in b/client/src/thirdparty/sqlite-3.4.2/sqlite3.pc.in new file mode 100644 index 0000000..2de6eff --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/sqlite3.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: SQLite +Description: SQL database engine +Version: @VERSION@ +Libs: -L${libdir} -lsqlite3 +Libs.private: -lpthread +Cflags: -I${includedir} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/alter.c b/client/src/thirdparty/sqlite-3.4.2/src/alter.c new file mode 100644 index 0000000..63b0bd7 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/alter.c @@ -0,0 +1,630 @@ +/* +** 2005 February 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. +** +************************************************************************* +** This file contains C code routines that used to generate VDBE code +** that implements the ALTER TABLE command. +** +** $Id: alter.c,v 1.41 2008/01/25 15:04:48 drh Exp $ +*/ +#include "sqliteInt.h" +#include + +/* +** The code in this file only exists if we are not omitting the +** ALTER TABLE logic from the build. +*/ +#ifndef SQLITE_OMIT_ALTERTABLE + + +/* +** This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TABLE or +** CREATE INDEX command. The second is a table name. The table name in +** the CREATE TABLE or CREATE INDEX statement is replaced with the third +** argument and the result returned. Examples: +** +** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def') +** -> 'CREATE TABLE def(a, b, c)' +** +** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def') +** -> 'CREATE INDEX i ON def(a, b, c)' +*/ +static void renameTableFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + + sqlite3 *db = sqlite3_user_data(context); + + /* The principle used to locate the table name in the CREATE TABLE + ** statement is that the table name is the first token that is immediatedly + ** followed by a left parenthesis - TK_LP - or "USING" TK_USING. + */ + if( zSql ){ + do { + if( !*zCsr ){ + /* Ran out of input before finding an opening bracket. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + } while( token==TK_SPACE ); + assert( len>0 ); + } while( token!=TK_LP && token!=TK_USING ); + + zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql, + zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, sqlite3_free); + } +} + +#ifndef SQLITE_OMIT_TRIGGER +/* This function is used by SQL generated to implement the +** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER +** statement. The second is a table name. The table name in the CREATE +** TRIGGER statement is replaced with the third argument and the result +** returned. This is analagous to renameTableFunc() above, except for CREATE +** TRIGGER, not CREATE INDEX and CREATE TABLE. +*/ +static void renameTriggerFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + unsigned char const *zSql = sqlite3_value_text(argv[0]); + unsigned char const *zTableName = sqlite3_value_text(argv[1]); + + int token; + Token tname; + int dist = 3; + unsigned char const *zCsr = zSql; + int len = 0; + char *zRet; + + sqlite3 *db = sqlite3_user_data(context); + + /* The principle used to locate the table name in the CREATE TRIGGER + ** statement is that the table name is the first token that is immediatedly + ** preceded by either TK_ON or TK_DOT and immediatedly followed by one + ** of TK_WHEN, TK_BEGIN or TK_FOR. + */ + if( zSql ){ + do { + + if( !*zCsr ){ + /* Ran out of input before finding the table name. Return NULL. */ + return; + } + + /* Store the token that zCsr points to in tname. */ + tname.z = zCsr; + tname.n = len; + + /* Advance zCsr to the next token. Store that token type in 'token', + ** and its length in 'len' (to be used next iteration of this loop). + */ + do { + zCsr += len; + len = sqlite3GetToken(zCsr, &token); + }while( token==TK_SPACE ); + assert( len>0 ); + + /* Variable 'dist' stores the number of tokens read since the most + ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN + ** token is read and 'dist' equals 2, the condition stated above + ** to be met. + ** + ** Note that ON cannot be a database, table or column name, so + ** there is no need to worry about syntax like + ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc. + */ + dist++; + if( token==TK_DOT || token==TK_ON ){ + dist = 0; + } + } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) ); + + /* Variable tname now contains the token that is the old table-name + ** in the CREATE TRIGGER statement. + */ + zRet = sqlite3MPrintf(db, "%.*s%Q%s", tname.z - zSql, zSql, + zTableName, tname.z+tname.n); + sqlite3_result_text(context, zRet, -1, sqlite3_free); + } +} +#endif /* !SQLITE_OMIT_TRIGGER */ + +/* +** Register built-in functions used to help implement ALTER TABLE +*/ +void sqlite3AlterFunctions(sqlite3 *db){ + static const struct { + char *zName; + signed char nArg; + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + { "sqlite_rename_table", 2, renameTableFunc}, +#ifndef SQLITE_OMIT_TRIGGER + { "sqlite_rename_trigger", 2, renameTriggerFunc}, +#endif + }; + int i; + + for(i=0; idb->aDb[1].pSchema; /* Temp db schema */ + + /* If the table is not located in the temp-db (in which case NULL is + ** returned, loop through the tables list of triggers. For each trigger + ** that is not part of the temp-db schema, add a clause to the WHERE + ** expression being built up in zWhere. + */ + if( pTab->pSchema!=pTempSchema ){ + sqlite3 *db = pParse->db; + for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){ + if( pTrig->pSchema==pTempSchema ){ + if( !zWhere ){ + zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->name); + }else{ + tmp = zWhere; + zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name); + sqlite3_free(tmp); + } + } + } + } + return zWhere; +} + +/* +** Generate code to drop and reload the internal representation of table +** pTab from the database, including triggers and temporary triggers. +** Argument zName is the name of the table in the database schema at +** the time the generated code is executed. This can be different from +** pTab->zName if this function is being called to code part of an +** "ALTER TABLE RENAME TO" statement. +*/ +static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ + Vdbe *v; + char *zWhere; + int iDb; /* Index of database containing pTab */ +#ifndef SQLITE_OMIT_TRIGGER + Trigger *pTrig; +#endif + + v = sqlite3GetVdbe(pParse); + if( !v ) return; + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); + +#ifndef SQLITE_OMIT_TRIGGER + /* Drop any table triggers from the internal schema. */ + for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){ + int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema); + assert( iTrigDb==iDb || iTrigDb==1 ); + sqlite3VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->name, 0); + } +#endif + + /* Drop the table and index from the internal schema */ + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); + + /* Reload the table, index and permanent trigger schemas. */ + zWhere = sqlite3MPrintf(pParse->db, "tbl_name=%Q", zName); + if( !zWhere ) return; + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC); + +#ifndef SQLITE_OMIT_TRIGGER + /* Now, if the table is not stored in the temp database, reload any temp + ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3VdbeAddOp4(v, OP_ParseSchema, 1, 0, 0, zWhere, P4_DYNAMIC); + } +#endif +} + +/* +** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" +** command. +*/ +void sqlite3AlterRenameTable( + Parse *pParse, /* Parser context. */ + SrcList *pSrc, /* The table to rename. */ + Token *pName /* The new table name. */ +){ + int iDb; /* Database that contains the table */ + char *zDb; /* Name of database iDb */ + Table *pTab; /* Table being renamed */ + char *zName = 0; /* NULL-terminated version of pName */ + sqlite3 *db = pParse->db; /* Database connection */ + int nTabName; /* Number of UTF-8 characters in zTabName */ + const char *zTabName; /* Original name of the table */ + Vdbe *v; +#ifndef SQLITE_OMIT_TRIGGER + char *zWhere = 0; /* Where clause to locate temp triggers */ +#endif + int isVirtualRename = 0; /* True if this is a v-table with an xRename() */ + + if( db->mallocFailed ) goto exit_rename_table; + assert( pSrc->nSrc==1 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + + pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase); + if( !pTab ) goto exit_rename_table; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + zDb = db->aDb[iDb].zName; + + /* Get a NULL terminated version of the new table name. */ + zName = sqlite3NameFromToken(db, pName); + if( !zName ) goto exit_rename_table; + + /* Check that a table or index named 'zName' does not already exist + ** in database iDb. If so, this is an error. + */ + if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ + sqlite3ErrorMsg(pParse, + "there is already another table or index with this name: %s", zName); + goto exit_rename_table; + } + + /* Make sure it is not a system table being altered, or a reserved name + ** that the table is being renamed to. + */ + if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); + goto exit_rename_table; + } + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_rename_table; + } + +#ifndef SQLITE_OMIT_VIEW + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName); + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_rename_table; + } + if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ + isVirtualRename = 1; + } +#endif + + /* Begin a transaction and code the VerifyCookie for database iDb. + ** Then modify the schema cookie (since the ALTER TABLE modifies the + ** schema). Open a statement transaction if the table is a virtual + ** table. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + goto exit_rename_table; + } + sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); + sqlite3ChangeCookie(pParse, iDb); + + /* If this is a virtual table, invoke the xRename() function if + ** one is defined. The xRename() callback will modify the names + ** of any resources used by the v-table implementation (including other + ** SQLite tables) that are identified by the name of the virtual table. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtualRename ){ + int i = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0); + sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pTab->pVtab, P4_VTAB); + } +#endif + + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + + /* Modify the sqlite_master table to use the new table name. */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " +#ifdef SQLITE_OMIT_TRIGGER + "sql = sqlite_rename_table(sql, %Q), " +#else + "sql = CASE " + "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)" + "ELSE sqlite_rename_table(sql, %Q) END, " +#endif + "tbl_name = %Q, " + "name = CASE " + "WHEN type='table' THEN %Q " + "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " + "'sqlite_autoindex_' || %Q || substr(name,%d+18) " + "ELSE name END " + "WHERE tbl_name=%Q AND " + "(type='table' OR type='index' OR type='trigger');", + zDb, SCHEMA_TABLE(iDb), zName, zName, zName, +#ifndef SQLITE_OMIT_TRIGGER + zName, +#endif + zName, nTabName, zTabName + ); + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* If the sqlite_sequence table exists in this database, then update + ** it with the new table name. + */ + if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){ + sqlite3NestedParse(pParse, + "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q", + zDb, zName, pTab->zName); + } +#endif + +#ifndef SQLITE_OMIT_TRIGGER + /* If there are TEMP triggers on this table, modify the sqlite_temp_master + ** table. Don't do this if the table being ALTERed is itself located in + ** the temp database. + */ + if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){ + sqlite3NestedParse(pParse, + "UPDATE sqlite_temp_master SET " + "sql = sqlite_rename_trigger(sql, %Q), " + "tbl_name = %Q " + "WHERE %s;", zName, zName, zWhere); + sqlite3_free(zWhere); + } +#endif + + /* Drop and reload the internal table schema. */ + reloadTableSchema(pParse, pTab, zName); + +exit_rename_table: + sqlite3SrcListDelete(pSrc); + sqlite3_free(zName); +} + + +/* +** This function is called after an "ALTER TABLE ... ADD" statement +** has been parsed. Argument pColDef contains the text of the new +** column definition. +** +** The Table structure pParse->pNewTable was extended to include +** the new column during parsing. +*/ +void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ + Table *pNew; /* Copy of pParse->pNewTable */ + Table *pTab; /* Table being altered */ + int iDb; /* Database number */ + const char *zDb; /* Database name */ + const char *zTab; /* Table name */ + char *zCol; /* Null-terminated column definition */ + Column *pCol; /* The new column */ + Expr *pDflt; /* Default value for the new column */ + sqlite3 *db; /* The database connection; */ + + if( pParse->nErr ) return; + pNew = pParse->pNewTable; + assert( pNew ); + + db = pParse->db; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + iDb = sqlite3SchemaToIndex(db, pNew->pSchema); + zDb = db->aDb[iDb].zName; + zTab = pNew->zName; + pCol = &pNew->aCol[pNew->nCol-1]; + pDflt = pCol->pDflt; + pTab = sqlite3FindTable(db, zTab, zDb); + assert( pTab ); + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + return; + } +#endif + + /* If the default value for the new column was specified with a + ** literal NULL, then set pDflt to 0. This simplifies checking + ** for an SQL NULL default below. + */ + if( pDflt && pDflt->op==TK_NULL ){ + pDflt = 0; + } + + /* Check that the new column is not specified as PRIMARY KEY or UNIQUE. + ** If there is a NOT NULL constraint, then the default value for the + ** column must not be NULL. + */ + if( pCol->isPrimKey ){ + sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column"); + return; + } + if( pNew->pIndex ){ + sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); + return; + } + if( pCol->notNull && !pDflt ){ + sqlite3ErrorMsg(pParse, + "Cannot add a NOT NULL column with default value NULL"); + return; + } + + /* Ensure the default expression is something that sqlite3ValueFromExpr() + ** can handle (i.e. not CURRENT_TIME etc.) + */ + if( pDflt ){ + sqlite3_value *pVal; + if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){ + db->mallocFailed = 1; + return; + } + if( !pVal ){ + sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default"); + return; + } + sqlite3ValueFree(pVal); + } + + /* Modify the CREATE TABLE statement. */ + zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n); + if( zCol ){ + char *zEnd = &zCol[pColDef->n-1]; + while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){ + *zEnd-- = '\0'; + } + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET " + "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) " + "WHERE type = 'table' AND name = %Q", + zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1, + zTab + ); + sqlite3_free(zCol); + } + + /* If the default value of the new column is NULL, then set the file + ** format to 2. If the default value of the new column is not NULL, + ** the file format becomes 3. + */ + sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2); + + /* Reload the schema of the modified table. */ + reloadTableSchema(pParse, pTab, pTab->zName); +} + +/* +** This function is called by the parser after the table-name in +** an "ALTER TABLE ADD" statement is parsed. Argument +** pSrc is the full-name of the table being altered. +** +** This routine makes a (partial) copy of the Table structure +** for the table being altered and sets Parse.pNewTable to point +** to it. Routines called by the parser as the column definition +** is parsed (i.e. sqlite3AddColumn()) add the new Column data to +** the copy. The copy of the Table structure is deleted by tokenize.c +** after parsing is finished. +** +** Routine sqlite3AlterFinishAddColumn() will be called to complete +** coding the "ALTER TABLE ... ADD" statement. +*/ +void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + Table *pNew; + Table *pTab; + Vdbe *v; + int iDb; + int i; + int nAlloc; + sqlite3 *db = pParse->db; + + /* Look up the table being altered. */ + assert( pParse->pNewTable==0 ); + assert( sqlite3BtreeHoldsAllMutexes(db) ); + if( db->mallocFailed ) goto exit_begin_add_column; + pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase); + if( !pTab ) goto exit_begin_add_column; + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be altered"); + goto exit_begin_add_column; + } +#endif + + /* Make sure this is not an attempt to ALTER a view. */ + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); + goto exit_begin_add_column; + } + + assert( pTab->addColOffset>0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + + /* Put a copy of the Table struct in Parse.pNewTable for the + ** sqlite3AddColumn() function and friends to modify. + */ + pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); + if( !pNew ) goto exit_begin_add_column; + pParse->pNewTable = pNew; + pNew->nRef = 1; + pNew->nCol = pTab->nCol; + assert( pNew->nCol>0 ); + nAlloc = (((pNew->nCol-1)/8)*8)+8; + assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); + pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); + pNew->zName = sqlite3DbStrDup(db, pTab->zName); + if( !pNew->aCol || !pNew->zName ){ + db->mallocFailed = 1; + goto exit_begin_add_column; + } + memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); + for(i=0; inCol; i++){ + Column *pCol = &pNew->aCol[i]; + pCol->zName = sqlite3DbStrDup(db, pCol->zName); + pCol->zColl = 0; + pCol->zType = 0; + pCol->pDflt = 0; + } + pNew->pSchema = db->aDb[iDb].pSchema; + pNew->addColOffset = pTab->addColOffset; + pNew->nRef = 1; + + /* Begin a transaction and increment the schema cookie. */ + sqlite3BeginWriteOperation(pParse, 0, iDb); + v = sqlite3GetVdbe(pParse); + if( !v ) goto exit_begin_add_column; + sqlite3ChangeCookie(pParse, iDb); + +exit_begin_add_column: + sqlite3SrcListDelete(pSrc); + return; +} +#endif /* SQLITE_ALTER_TABLE */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/analyze.c b/client/src/thirdparty/sqlite-3.4.2/src/analyze.c new file mode 100644 index 0000000..4168fe6 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/analyze.c @@ -0,0 +1,425 @@ +/* +** 2005 July 8 +** +** 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 associated with the ANALYZE command. +** +** @(#) $Id: analyze.c,v 1.41 2008/01/25 15:04:49 drh Exp $ +*/ +#ifndef SQLITE_OMIT_ANALYZE +#include "sqliteInt.h" + +/* +** This routine generates code that opens the sqlite_stat1 table on cursor +** iStatCur. +** +** If the sqlite_stat1 tables does not previously exist, it is created. +** If it does previously exist, all entires associated with table zWhere +** are removed. If zWhere==0 then all entries are removed. +*/ +static void openStatTable( + Parse *pParse, /* Parsing context */ + int iDb, /* The database we are looking in */ + int iStatCur, /* Open the sqlite_stat1 table on this cursor */ + const char *zWhere /* Delete entries associated with this table */ +){ + sqlite3 *db = pParse->db; + Db *pDb; + int iRootPage; + int createStat1 = 0; + Table *pStat; + Vdbe *v = sqlite3GetVdbe(pParse); + + if( v==0 ) return; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3VdbeDb(v)==db ); + pDb = &db->aDb[iDb]; + if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){ + /* The sqlite_stat1 tables does not exist. Create it. + ** Note that a side-effect of the CREATE TABLE statement is to leave + ** the rootpage of the new table in register pParse->regRoot. This is + ** important because the OpenWrite opcode below will be needing it. */ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)", + pDb->zName + ); + iRootPage = pParse->regRoot; + createStat1 = 1; /* Cause rootpage to be taken from top of stack */ + }else if( zWhere ){ + /* The sqlite_stat1 table exists. Delete all entries associated with + ** the table zWhere. */ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", + pDb->zName, zWhere + ); + iRootPage = pStat->tnum; + }else{ + /* The sqlite_stat1 table already exists. Delete all rows. */ + iRootPage = pStat->tnum; + sqlite3VdbeAddOp2(v, OP_Clear, pStat->tnum, iDb); + } + + /* Open the sqlite_stat1 table for writing. Unless it was created + ** by this vdbe program, lock it for writing at the shared-cache level. + ** If this vdbe did create the sqlite_stat1 table, then it must have + ** already obtained a schema-lock, making the write-lock redundant. + */ + if( !createStat1 ){ + sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); + } + sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb); + sqlite3VdbeChangeP5(v, createStat1); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3); +} + +/* +** Generate code to do an analysis of all indices associated with +** a single table. +*/ +static void analyzeOneTable( + Parse *pParse, /* Parser context */ + Table *pTab, /* Table whose indices are to be analyzed */ + int iStatCur, /* Cursor that writes to the sqlite_stat1 table */ + int iMem /* Available memory locations begin here */ +){ + Index *pIdx; /* An index to being analyzed */ + int iIdxCur; /* Cursor number for index being analyzed */ + int nCol; /* Number of columns in the index */ + Vdbe *v; /* The virtual machine being built up */ + int i; /* Loop counter */ + int topOfLoop; /* The top of the loop */ + int endOfLoop; /* The end of the loop */ + int addr; /* The address of an instruction */ + int iDb; /* Index of database containing pTab */ + + v = sqlite3GetVdbe(pParse); + if( v==0 || pTab==0 || pTab->pIndex==0 ){ + /* Do no analysis for tables that have no indices */ + return; + } + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 ); +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0, + pParse->db->aDb[iDb].zName ) ){ + return; + } +#endif + + /* Establish a read-lock on the table at the shared-cache level. */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + + iIdxCur = pParse->nTab; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + int regFields; /* Register block for building records */ + int regRec; /* Register holding completed record */ + int regTemp; /* Temporary use register */ + int regCol; /* Content of a column from the table being analyzed */ + int regRowid; /* Rowid for the inserted record */ + int regF2; + + /* Open a cursor to the index to be analyzed + */ + assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); + sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, + (char *)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + nCol = pIdx->nColumn; + regFields = iMem+nCol*2; + regTemp = regRowid = regCol = regFields+3; + regRec = regCol+1; + if( regRec>pParse->nMem ){ + pParse->nMem = regRec; + } + sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, nCol+1); + + /* Memory cells are used as follows: + ** + ** mem[iMem]: The total number of rows in the table. + ** mem[iMem+1]: Number of distinct values in column 1 + ** ... + ** mem[iMem+nCol]: Number of distinct values in column N + ** mem[iMem+nCol+1] Last observed value of column 1 + ** ... + ** mem[iMem+nCol+nCol]: Last observed value of column N + ** + ** Cells iMem through iMem+nCol are initialized to 0. The others + ** are initialized to NULL. + */ + for(i=0; i<=nCol; i++){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i); + } + for(i=0; i0 then it is always the case the D>0 so division by zero + ** is never possible. + */ + addr = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); + sqlite3VdbeAddOp4(v, OP_String8, 0, regFields, 0, pTab->zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, regFields+1, 0, pIdx->zName, 0); + regF2 = regFields+2; + sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regF2); + for(i=0; idb; + Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ + HashElem *k; + int iStatCur; + int iMem; + + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab++; + openStatTable(pParse, iDb, iStatCur, 0); + iMem = pParse->nMem+1; + for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ + Table *pTab = (Table*)sqliteHashData(k); + analyzeOneTable(pParse, pTab, iStatCur, iMem); + } + loadAnalysis(pParse, iDb); +} + +/* +** Generate code that will do an analysis of a single table in +** a database. +*/ +static void analyzeTable(Parse *pParse, Table *pTab){ + int iDb; + int iStatCur; + + assert( pTab!=0 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + iStatCur = pParse->nTab++; + openStatTable(pParse, iDb, iStatCur, pTab->zName); + analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem+1); + loadAnalysis(pParse, iDb); +} + +/* +** Generate code for the ANALYZE command. The parser calls this routine +** when it recognizes an ANALYZE command. +** +** ANALYZE -- 1 +** ANALYZE -- 2 +** ANALYZE ?.? -- 3 +** +** Form 1 causes all indices in all attached databases to be analyzed. +** Form 2 analyzes all indices the single database named. +** Form 3 analyzes all indices associated with the named table. +*/ +void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ + sqlite3 *db = pParse->db; + int iDb; + int i; + char *z, *zDb; + Table *pTab; + Token *pTableName; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return; + } + + if( pName1==0 ){ + /* Form 1: Analyze everything */ + for(i=0; inDb; i++){ + if( i==1 ) continue; /* Do not analyze the TEMP database */ + analyzeDatabase(pParse, i); + } + }else if( pName2==0 || pName2->n==0 ){ + /* Form 2: Analyze the database or table named */ + iDb = sqlite3FindDb(db, pName1); + if( iDb>=0 ){ + analyzeDatabase(pParse, iDb); + }else{ + z = sqlite3NameFromToken(db, pName1); + if( z ){ + pTab = sqlite3LocateTable(pParse, 0, z, 0); + sqlite3_free(z); + if( pTab ){ + analyzeTable(pParse, pTab); + } + } + } + }else{ + /* Form 3: Analyze the fully qualified table name */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName); + if( iDb>=0 ){ + zDb = db->aDb[iDb].zName; + z = sqlite3NameFromToken(db, pTableName); + if( z ){ + pTab = sqlite3LocateTable(pParse, 0, z, zDb); + sqlite3_free(z); + if( pTab ){ + analyzeTable(pParse, pTab); + } + } + } + } +} + +/* +** Used to pass information from the analyzer reader through to the +** callback routine. +*/ +typedef struct analysisInfo analysisInfo; +struct analysisInfo { + sqlite3 *db; + const char *zDatabase; +}; + +/* +** This callback is invoked once for each index when reading the +** sqlite_stat1 table. +** +** argv[0] = name of the index +** argv[1] = results of analysis - on integer for each column +*/ +static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){ + analysisInfo *pInfo = (analysisInfo*)pData; + Index *pIndex; + int i, c; + unsigned int v; + const char *z; + + assert( argc==2 ); + if( argv==0 || argv[0]==0 || argv[1]==0 ){ + return 0; + } + pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase); + if( pIndex==0 ){ + return 0; + } + z = argv[1]; + for(i=0; *z && i<=pIndex->nColumn; i++){ + v = 0; + while( (c=z[0])>='0' && c<='9' ){ + v = v*10 + c - '0'; + z++; + } + pIndex->aiRowEst[i] = v; + if( *z==' ' ) z++; + } + return 0; +} + +/* +** Load the content of the sqlite_stat1 table into the index hash tables. +*/ +int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ + analysisInfo sInfo; + HashElem *i; + char *zSql; + int rc; + + assert( iDb>=0 && iDbnDb ); + assert( db->aDb[iDb].pBt!=0 ); + assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + + /* Clear any prior statistics */ + for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ + Index *pIdx = sqliteHashData(i); + sqlite3DefaultRowEst(pIdx); + } + + /* Check to make sure the sqlite_stat1 table existss */ + sInfo.db = db; + sInfo.zDatabase = db->aDb[iDb].zName; + if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ + return SQLITE_ERROR; + } + + + /* Load new statistics out of the sqlite_stat1 table */ + zSql = sqlite3MPrintf(db, "SELECT idx, stat FROM %Q.sqlite_stat1", + sInfo.zDatabase); + (void)sqlite3SafetyOff(db); + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + (void)sqlite3SafetyOn(db); + sqlite3_free(zSql); + return rc; +} + + +#endif /* SQLITE_OMIT_ANALYZE */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/attach.c b/client/src/thirdparty/sqlite-3.4.2/src/attach.c new file mode 100644 index 0000000..67a34b7 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/attach.c @@ -0,0 +1,527 @@ +/* +** 2003 April 6 +** +** 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 used to implement the ATTACH and DETACH commands. +** +** $Id: attach.c,v 1.71 2008/02/06 14:11:35 drh Exp $ +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_ATTACH +/* +** Resolve an expression that was part of an ATTACH or DETACH statement. This +** is slightly different from resolving a normal SQL expression, because simple +** identifiers are treated as strings, not possible column names or aliases. +** +** i.e. if the parser sees: +** +** ATTACH DATABASE abc AS def +** +** it treats the two expressions as literal strings 'abc' and 'def' instead of +** looking for columns of the same name. +** +** This only applies to the root node of pExpr, so the statement: +** +** ATTACH DATABASE abc||def AS 'db2' +** +** will fail because neither abc or def can be resolved. +*/ +static int resolveAttachExpr(NameContext *pName, Expr *pExpr) +{ + int rc = SQLITE_OK; + if( pExpr ){ + if( pExpr->op!=TK_ID ){ + rc = sqlite3ExprResolveNames(pName, pExpr); + if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span); + return SQLITE_ERROR; + } + }else{ + pExpr->op = TK_STRING; + } + } + return rc; +} + +/* +** An SQL user-function registered to do the work of an ATTACH statement. The +** three arguments to the function come directly from an attach statement: +** +** ATTACH DATABASE x AS y KEY z +** +** SELECT sqlite_attach(x, y, z) +** +** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the +** third argument. +*/ +static void attachFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + int rc = 0; + sqlite3 *db = sqlite3_user_data(context); + const char *zName; + const char *zFile; + Db *aNew; + char *zErrDyn = 0; + char zErr[128]; + + zFile = (const char *)sqlite3_value_text(argv[0]); + zName = (const char *)sqlite3_value_text(argv[1]); + if( zFile==0 ) zFile = ""; + if( zName==0 ) zName = ""; + + /* Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=SQLITE_MAX_ATTACHED+2 ){ + sqlite3_snprintf( + sizeof(zErr), zErr, "too many attached databases - max %d", + SQLITE_MAX_ATTACHED + ); + goto attach_error; + } + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot ATTACH database within transaction"); + goto attach_error; + } + for(i=0; inDb; i++){ + char *z = db->aDb[i].zName; + if( z && zName && sqlite3StrICmp(z, zName)==0 ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "database %s is already in use", zName); + goto attach_error; + } + } + + /* Allocate the new entry in the db->aDb[] array and initialise the schema + ** hash tables. + */ + if( db->aDb==db->aDbStatic ){ + aNew = sqlite3_malloc( sizeof(db->aDb[0])*3 ); + if( aNew==0 ){ + db->mallocFailed = 1; + return; + } + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3_realloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ){ + db->mallocFailed = 1; + return; + } + } + db->aDb = aNew; + aNew = &db->aDb[db->nDb++]; + memset(aNew, 0, sizeof(*aNew)); + + /* Open the database file. If the btree is successfully opened, use + ** it to obtain the database schema. At this point the schema may + ** or may not be initialised. + */ + rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE, + db->openFlags | SQLITE_OPEN_MAIN_DB, + &aNew->pBt); + if( rc==SQLITE_OK ){ + aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); + if( !aNew->pSchema ){ + rc = SQLITE_NOMEM; + }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "attached databases must use the same text encoding as main database"); + goto attach_error; + } + sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode); + } + aNew->zName = sqlite3DbStrDup(db, zName); + aNew->safety_level = 3; + +#if SQLITE_HAS_CODEC + { + extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); + extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); + int nKey; + char *zKey; + int t = sqlite3_value_type(argv[2]); + switch( t ){ + case SQLITE_INTEGER: + case SQLITE_FLOAT: + zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); + rc = SQLITE_ERROR; + break; + + case SQLITE_TEXT: + case SQLITE_BLOB: + nKey = sqlite3_value_bytes(argv[2]); + zKey = (char *)sqlite3_value_blob(argv[2]); + sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; + + case SQLITE_NULL: + /* No key specified. Use the key from the main database */ + sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); + sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); + break; + } + } +#endif + + /* If the file was opened successfully, read the schema for the new database. + ** If this fails, or if opening the file failed, then close the file and + ** remove the entry from the db->aDb[] array. i.e. put everything back the way + ** we found it. + */ + if( rc==SQLITE_OK ){ + (void)sqlite3SafetyOn(db); + sqlite3BtreeEnterAll(db); + rc = sqlite3Init(db, &zErrDyn); + sqlite3BtreeLeaveAll(db); + (void)sqlite3SafetyOff(db); + } + if( rc ){ + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; + } + sqlite3ResetInternalSchema(db, 0); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + sqlite3_snprintf(sizeof(zErr),zErr, "out of memory"); + }else{ + sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile); + } + goto attach_error; + } + + return; + +attach_error: + /* Return an error if we get here */ + if( zErrDyn ){ + sqlite3_result_error(context, zErrDyn, -1); + sqlite3_free(zErrDyn); + }else{ + zErr[sizeof(zErr)-1] = 0; + sqlite3_result_error(context, zErr, -1); + } + if( rc ) sqlite3_result_error_code(context, rc); +} + +/* +** An SQL user-function registered to do the work of an DETACH statement. The +** three arguments to the function come directly from a detach statement: +** +** DETACH DATABASE x +** +** SELECT sqlite_detach(x) +*/ +static void detachFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zName = (const char *)sqlite3_value_text(argv[0]); + sqlite3 *db = sqlite3_user_data(context); + int i; + Db *pDb = 0; + char zErr[128]; + + if( zName==0 ) zName = ""; + for(i=0; inDb; i++){ + pDb = &db->aDb[i]; + if( pDb->pBt==0 ) continue; + if( sqlite3StrICmp(pDb->zName, zName)==0 ) break; + } + + if( i>=db->nDb ){ + sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName); + goto detach_error; + } + if( i<2 ){ + sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName); + goto detach_error; + } + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot DETACH database within transaction"); + goto detach_error; + } + if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){ + sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName); + goto detach_error; + } + + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + pDb->pSchema = 0; + sqlite3ResetInternalSchema(db, 0); + return; + +detach_error: + sqlite3_result_error(context, zErr, -1); +} + +/* +** This procedure generates VDBE code for a single invocation of either the +** sqlite_detach() or sqlite_attach() SQL user functions. +*/ +static void codeAttach( + Parse *pParse, /* The parser context */ + int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ + const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */ + int nFunc, /* Number of args to pass to zFunc */ + Expr *pAuthArg, /* Expression to pass to authorization callback */ + Expr *pFilename, /* Name of database file */ + Expr *pDbname, /* Name of the database to use internally */ + Expr *pKey /* Database key for encryption extension */ +){ + int rc; + NameContext sName; + Vdbe *v; + FuncDef *pFunc; + sqlite3* db = pParse->db; + int regArgs; + +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( db->mallocFailed || pAuthArg ); + if( pAuthArg ){ + char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span); + if( !zAuthArg ){ + goto attach_end; + } + rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0); + sqlite3_free(zAuthArg); + if(rc!=SQLITE_OK ){ + goto attach_end; + } + } +#endif /* SQLITE_OMIT_AUTHORIZATION */ + + memset(&sName, 0, sizeof(NameContext)); + sName.pParse = pParse; + + if( + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) || + SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey)) + ){ + pParse->nErr++; + goto attach_end; + } + + v = sqlite3GetVdbe(pParse); + regArgs = sqlite3GetTempRange(pParse, 3); + sqlite3ExprCode(pParse, pFilename, regArgs); + sqlite3ExprCode(pParse, pDbname, regArgs+1); + sqlite3ExprCode(pParse, pKey, regArgs+2); + + assert( v || db->mallocFailed ); + if( v ){ + sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs); + sqlite3VdbeChangeP5(v, nFunc); + pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); + sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); + + /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this + ** statement only). For DETACH, set it to false (expire all existing + ** statements). + */ + sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); + } + +attach_end: + sqlite3ExprDelete(pFilename); + sqlite3ExprDelete(pDbname); + sqlite3ExprDelete(pKey); +} + +/* +** Called by the parser to compile a DETACH statement. +** +** DETACH pDbname +*/ +void sqlite3Detach(Parse *pParse, Expr *pDbname){ + codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname); +} + +/* +** Called by the parser to compile an ATTACH statement. +** +** ATTACH p AS pDbname KEY pKey +*/ +void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ + codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey); +} +#endif /* SQLITE_OMIT_ATTACH */ + +/* +** Register the functions sqlite_attach and sqlite_detach. +*/ +void sqlite3AttachFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_ATTACH + static const int enc = SQLITE_UTF8; + sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0); + sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0); +#endif +} + +/* +** Initialize a DbFixer structure. This routine must be called prior +** to passing the structure to one of the sqliteFixAAAA() routines below. +** +** The return value indicates whether or not fixation is required. TRUE +** means we do need to fix the database references, FALSE means we do not. +*/ +int sqlite3FixInit( + DbFixer *pFix, /* The fixer to be initialized */ + Parse *pParse, /* Error messages will be written here */ + int iDb, /* This is the database that must be used */ + const char *zType, /* "view", "trigger", or "index" */ + const Token *pName /* Name of the view, trigger, or index */ +){ + sqlite3 *db; + + if( iDb<0 || iDb==1 ) return 0; + db = pParse->db; + assert( db->nDb>iDb ); + pFix->pParse = pParse; + pFix->zDb = db->aDb[iDb].zName; + pFix->zType = zType; + pFix->pName = pName; + return 1; +} + +/* +** The following set of routines walk through the parse tree and assign +** a specific database to all table references where the database name +** was left unspecified in the original SQL statement. The pFix structure +** must have been initialized by a prior call to sqlite3FixInit(). +** +** These routines are used to make sure that an index, trigger, or +** view in one database does not refer to objects in a different database. +** (Exception: indices, triggers, and views in the TEMP database are +** allowed to refer to anything.) If a reference is explicitly made +** to an object in a different database, an error message is added to +** pParse->zErrMsg and these routines return non-zero. If everything +** checks out, these routines return 0. +*/ +int sqlite3FixSrcList( + DbFixer *pFix, /* Context of the fixation */ + SrcList *pList /* The Source list to check and modify */ +){ + int i; + const char *zDb; + struct SrcList_item *pItem; + + if( pList==0 ) return 0; + zDb = pFix->zDb; + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pItem->zDatabase==0 ){ + pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb); + }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){ + sqlite3ErrorMsg(pFix->pParse, + "%s %T cannot reference objects in database %s", + pFix->zType, pFix->pName, pItem->zDatabase); + return 1; + } +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) + if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; + if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; +#endif + } + return 0; +} +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) +int sqlite3FixSelect( + DbFixer *pFix, /* Context of the fixation */ + Select *pSelect /* The SELECT statement to be fixed to one database */ +){ + while( pSelect ){ + if( sqlite3FixExprList(pFix, pSelect->pEList) ){ + return 1; + } + if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pWhere) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pSelect->pHaving) ){ + return 1; + } + pSelect = pSelect->pPrior; + } + return 0; +} +int sqlite3FixExpr( + DbFixer *pFix, /* Context of the fixation */ + Expr *pExpr /* The expression to be fixed to one database */ +){ + while( pExpr ){ + if( sqlite3FixSelect(pFix, pExpr->pSelect) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pExpr->pList) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pExpr->pRight) ){ + return 1; + } + pExpr = pExpr->pLeft; + } + return 0; +} +int sqlite3FixExprList( + DbFixer *pFix, /* Context of the fixation */ + ExprList *pList /* The expression to be fixed to one database */ +){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return 0; + for(i=0, pItem=pList->a; inExpr; i++, pItem++){ + if( sqlite3FixExpr(pFix, pItem->pExpr) ){ + return 1; + } + } + return 0; +} +#endif + +#ifndef SQLITE_OMIT_TRIGGER +int sqlite3FixTriggerStep( + DbFixer *pFix, /* Context of the fixation */ + TriggerStep *pStep /* The trigger step be fixed to one database */ +){ + while( pStep ){ + if( sqlite3FixSelect(pFix, pStep->pSelect) ){ + return 1; + } + if( sqlite3FixExpr(pFix, pStep->pWhere) ){ + return 1; + } + if( sqlite3FixExprList(pFix, pStep->pExprList) ){ + return 1; + } + pStep = pStep->pNext; + } + return 0; +} +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/auth.c b/client/src/thirdparty/sqlite-3.4.2/src/auth.c new file mode 100644 index 0000000..5630c23 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/auth.c @@ -0,0 +1,234 @@ +/* +** 2003 January 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. +** +************************************************************************* +** This file contains code used to implement the sqlite3_set_authorizer() +** API. This facility is an optional feature of the library. Embedded +** systems that do not need this facility may omit it by recompiling +** the library with -DSQLITE_OMIT_AUTHORIZATION=1 +** +** $Id: auth.c,v 1.29 2007/09/18 15:55:07 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** All of the code in this file may be omitted by defining a single +** macro. +*/ +#ifndef SQLITE_OMIT_AUTHORIZATION + +/* +** Set or clear the access authorization function. +** +** The access authorization function is be called during the compilation +** phase to verify that the user has read and/or write access permission on +** various fields of the database. The first argument to the auth function +** is a copy of the 3rd argument to this routine. The second argument +** to the auth function is one of these constants: +** +** SQLITE_CREATE_INDEX +** SQLITE_CREATE_TABLE +** SQLITE_CREATE_TEMP_INDEX +** SQLITE_CREATE_TEMP_TABLE +** SQLITE_CREATE_TEMP_TRIGGER +** SQLITE_CREATE_TEMP_VIEW +** SQLITE_CREATE_TRIGGER +** SQLITE_CREATE_VIEW +** SQLITE_DELETE +** SQLITE_DROP_INDEX +** SQLITE_DROP_TABLE +** SQLITE_DROP_TEMP_INDEX +** SQLITE_DROP_TEMP_TABLE +** SQLITE_DROP_TEMP_TRIGGER +** SQLITE_DROP_TEMP_VIEW +** SQLITE_DROP_TRIGGER +** SQLITE_DROP_VIEW +** SQLITE_INSERT +** SQLITE_PRAGMA +** SQLITE_READ +** SQLITE_SELECT +** SQLITE_TRANSACTION +** SQLITE_UPDATE +** +** The third and fourth arguments to the auth function are the name of +** the table and the column that are being accessed. The auth function +** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If +** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY +** means that the SQL statement will never-run - the sqlite3_exec() call +** will return with an error. SQLITE_IGNORE means that the SQL statement +** should run but attempts to read the specified column will return NULL +** and attempts to write the column will be ignored. +** +** Setting the auth function to NULL disables this hook. The default +** setting of the auth function is NULL. +*/ +int sqlite3_set_authorizer( + sqlite3 *db, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pArg +){ + sqlite3_mutex_enter(db->mutex); + db->xAuth = xAuth; + db->pAuthArg = pArg; + sqlite3ExpirePreparedStatements(db); + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +/* +** Write an error message into pParse->zErrMsg that explains that the +** user-supplied authorization function returned an illegal value. +*/ +static void sqliteAuthBadReturnCode(Parse *pParse, int rc){ + sqlite3ErrorMsg(pParse, "illegal return value (%d) from the " + "authorization function - should be SQLITE_OK, SQLITE_IGNORE, " + "or SQLITE_DENY", rc); + pParse->rc = SQLITE_ERROR; +} + +/* +** The pExpr should be a TK_COLUMN expression. The table referred to +** is in pTabList or else it is the NEW or OLD table of a trigger. +** Check to see if it is OK to read this particular column. +** +** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN +** instruction into a TK_NULL. If the auth function returns SQLITE_DENY, +** then generate an error. +*/ +void sqlite3AuthRead( + Parse *pParse, /* The parser context */ + Expr *pExpr, /* The expression to check authorization on */ + Schema *pSchema, /* The schema of the expression */ + SrcList *pTabList /* All table that pExpr might refer to */ +){ + sqlite3 *db = pParse->db; + int rc; + Table *pTab = 0; /* The table being read */ + const char *zCol; /* Name of the column of the table */ + int iSrc; /* Index in pTabList->a[] of table being read */ + const char *zDBase; /* Name of database being accessed */ + TriggerStack *pStack; /* The stack of current triggers */ + int iDb; /* The index of the database the expression refers to */ + + if( db->xAuth==0 ) return; + if( pExpr->op!=TK_COLUMN ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pSchema); + if( iDb<0 ){ + /* An attempt to read a column out of a subquery or other + ** temporary table. */ + return; + } + for(iSrc=0; pTabList && iSrcnSrc; iSrc++){ + if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; + } + if( iSrc>=0 && pTabList && iSrcnSrc ){ + pTab = pTabList->a[iSrc].pTab; + }else if( (pStack = pParse->trigStack)!=0 ){ + /* This must be an attempt to read the NEW or OLD pseudo-tables + ** of a trigger. + */ + assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx ); + pTab = pStack->pTab; + } + if( pTab==0 ) return; + if( pExpr->iColumn>=0 ){ + assert( pExpr->iColumnnCol ); + zCol = pTab->aCol[pExpr->iColumn].zName; + }else if( pTab->iPKey>=0 ){ + assert( pTab->iPKeynCol ); + zCol = pTab->aCol[pTab->iPKey].zName; + }else{ + zCol = "ROWID"; + } + assert( iDb>=0 && iDbnDb ); + zDBase = db->aDb[iDb].zName; + rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, + pParse->zAuthContext); + if( rc==SQLITE_IGNORE ){ + pExpr->op = TK_NULL; + }else if( rc==SQLITE_DENY ){ + if( db->nDb>2 || iDb!=0 ){ + sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited", + zDBase, pTab->zName, zCol); + }else{ + sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol); + } + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_OK ){ + sqliteAuthBadReturnCode(pParse, rc); + } +} + +/* +** Do an authorization check using the code and arguments given. Return +** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY +** is returned, then the error count and error message in pParse are +** modified appropriately. +*/ +int sqlite3AuthCheck( + Parse *pParse, + int code, + const char *zArg1, + const char *zArg2, + const char *zArg3 +){ + sqlite3 *db = pParse->db; + int rc; + + /* Don't do any authorization checks if the database is initialising + ** or if the parser is being invoked from within sqlite3_declare_vtab. + */ + if( db->init.busy || IN_DECLARE_VTAB ){ + return SQLITE_OK; + } + + if( db->xAuth==0 ){ + return SQLITE_OK; + } + rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext); + if( rc==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized"); + pParse->rc = SQLITE_AUTH; + }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){ + rc = SQLITE_DENY; + sqliteAuthBadReturnCode(pParse, rc); + } + return rc; +} + +/* +** Push an authorization context. After this routine is called, the +** zArg3 argument to authorization callbacks will be zContext until +** popped. Or if pParse==0, this routine is a no-op. +*/ +void sqlite3AuthContextPush( + Parse *pParse, + AuthContext *pContext, + const char *zContext +){ + pContext->pParse = pParse; + if( pParse ){ + pContext->zAuthContext = pParse->zAuthContext; + pParse->zAuthContext = zContext; + } +} + +/* +** Pop an authorization context that was previously pushed +** by sqlite3AuthContextPush +*/ +void sqlite3AuthContextPop(AuthContext *pContext){ + if( pContext->pParse ){ + pContext->pParse->zAuthContext = pContext->zAuthContext; + pContext->pParse = 0; + } +} + +#endif /* SQLITE_OMIT_AUTHORIZATION */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/btmutex.c b/client/src/thirdparty/sqlite-3.4.2/src/btmutex.c new file mode 100644 index 0000000..58a1b56 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/btmutex.c @@ -0,0 +1,317 @@ +/* +** 2007 August 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. +** +************************************************************************* +** +** $Id: btmutex.c,v 1.9 2008/01/23 12:52:41 drh Exp $ +** +** This file contains code used to implement mutexes on Btree objects. +** This code really belongs in btree.c. But btree.c is getting too +** big and we want to break it down some. This packaged seemed like +** a good breakout. +*/ +#include "btreeInt.h" +#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) + + +/* +** Enter a mutex on the given BTree object. +** +** If the object is not sharable, then no mutex is ever required +** and this routine is a no-op. The underlying mutex is non-recursive. +** But we keep a reference count in Btree.wantToLock so the behavior +** of this interface is recursive. +** +** To avoid deadlocks, multiple Btrees are locked in the same order +** by all database connections. The p->pNext is a list of other +** Btrees belonging to the same database connection as the p Btree +** which need to be locked after p. If we cannot get a lock on +** p, then first unlock all of the others on p->pNext, then wait +** for the lock to become available on p, then relock all of the +** subsequent Btrees that desire a lock. +*/ +void sqlite3BtreeEnter(Btree *p){ + Btree *pLater; + + /* Some basic sanity checking on the Btree. The list of Btrees + ** connected by pNext and pPrev should be in sorted order by + ** Btree.pBt value. All elements of the list should belong to + ** the same connection. Only shared Btrees are on the list. */ + assert( p->pNext==0 || p->pNext->pBt>p->pBt ); + assert( p->pPrev==0 || p->pPrev->pBtpBt ); + assert( p->pNext==0 || p->pNext->db==p->db ); + assert( p->pPrev==0 || p->pPrev->db==p->db ); + assert( p->sharable || (p->pNext==0 && p->pPrev==0) ); + + /* Check for locking consistency */ + assert( !p->locked || p->wantToLock>0 ); + assert( p->sharable || p->wantToLock==0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + if( !p->sharable ) return; + p->wantToLock++; + if( p->locked ) return; + +#ifndef SQLITE_MUTEX_NOOP + /* In most cases, we should be able to acquire the lock we + ** want without having to go throught the ascending lock + ** procedure that follows. Just be sure not to block. + */ + if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){ + p->locked = 1; + return; + } + + /* To avoid deadlock, first release all locks with a larger + ** BtShared address. Then acquire our lock. Then reacquire + ** the other BtShared locks that we used to hold in ascending + ** order. + */ + for(pLater=p->pNext; pLater; pLater=pLater->pNext){ + assert( pLater->sharable ); + assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt ); + assert( !pLater->locked || pLater->wantToLock>0 ); + if( pLater->locked ){ + sqlite3_mutex_leave(pLater->pBt->mutex); + pLater->locked = 0; + } + } + sqlite3_mutex_enter(p->pBt->mutex); + p->locked = 1; + for(pLater=p->pNext; pLater; pLater=pLater->pNext){ + if( pLater->wantToLock ){ + sqlite3_mutex_enter(pLater->pBt->mutex); + pLater->locked = 1; + } + } +#endif /* SQLITE_MUTEX_NOOP */ +} + +/* +** Exit the recursive mutex on a Btree. +*/ +void sqlite3BtreeLeave(Btree *p){ + if( p->sharable ){ + assert( p->wantToLock>0 ); + p->wantToLock--; + if( p->wantToLock==0 ){ + assert( p->locked ); + sqlite3_mutex_leave(p->pBt->mutex); + p->locked = 0; + } + } +} + +#ifndef NDEBUG +/* +** Return true if the BtShared mutex is held on the btree. +** +** This routine makes no determination one why or another if the +** database connection mutex is held. +** +** This routine is used only from within assert() statements. +*/ +int sqlite3BtreeHoldsMutex(Btree *p){ + return (p->sharable==0 || + (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex))); +} +#endif + + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Enter and leave a mutex on a Btree given a cursor owned by that +** Btree. These entry points are used by incremental I/O and can be +** omitted if that module is not used. +*/ +void sqlite3BtreeEnterCursor(BtCursor *pCur){ + sqlite3BtreeEnter(pCur->pBtree); +} +void sqlite3BtreeLeaveCursor(BtCursor *pCur){ + sqlite3BtreeLeave(pCur->pBtree); +} +#endif /* SQLITE_OMIT_INCRBLOB */ + + +/* +** Enter the mutex on every Btree associated with a database +** connection. This is needed (for example) prior to parsing +** a statement since we will be comparing table and column names +** against all schemas and we do not want those schemas being +** reset out from under us. +** +** There is a corresponding leave-all procedures. +** +** Enter the mutexes in accending order by BtShared pointer address +** to avoid the possibility of deadlock when two threads with +** two or more btrees in common both try to lock all their btrees +** at the same instant. +*/ +void sqlite3BtreeEnterAll(sqlite3 *db){ + int i; + Btree *p, *pLater; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; inDb; i++){ + p = db->aDb[i].pBt; + if( p && p->sharable ){ + p->wantToLock++; + if( !p->locked ){ + assert( p->wantToLock==1 ); + while( p->pPrev ) p = p->pPrev; + while( p->locked && p->pNext ) p = p->pNext; + for(pLater = p->pNext; pLater; pLater=pLater->pNext){ + if( pLater->locked ){ + sqlite3_mutex_leave(pLater->pBt->mutex); + pLater->locked = 0; + } + } + while( p ){ + sqlite3_mutex_enter(p->pBt->mutex); + p->locked++; + p = p->pNext; + } + } + } + } +} +void sqlite3BtreeLeaveAll(sqlite3 *db){ + int i; + Btree *p; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; inDb; i++){ + p = db->aDb[i].pBt; + if( p && p->sharable ){ + assert( p->wantToLock>0 ); + p->wantToLock--; + if( p->wantToLock==0 ){ + assert( p->locked ); + sqlite3_mutex_leave(p->pBt->mutex); + p->locked = 0; + } + } + } +} + +#ifndef NDEBUG +/* +** Return true if the current thread holds the database connection +** mutex and all required BtShared mutexes. +** +** This routine is used inside assert() statements only. +*/ +int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ + int i; + if( !sqlite3_mutex_held(db->mutex) ){ + return 0; + } + for(i=0; inDb; i++){ + Btree *p; + p = db->aDb[i].pBt; + if( p && p->sharable && + (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ + return 0; + } + } + return 1; +} +#endif /* NDEBUG */ + +/* +** Potentially dd a new Btree pointer to a BtreeMutexArray. +** Really only add the Btree if it can possibly be shared with +** another database connection. +** +** The Btrees are kept in sorted order by pBtree->pBt. That +** way when we go to enter all the mutexes, we can enter them +** in order without every having to backup and retry and without +** worrying about deadlock. +** +** The number of shared btrees will always be small (usually 0 or 1) +** so an insertion sort is an adequate algorithm here. +*/ +void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ + int i, j; + BtShared *pBt; + if( pBtree==0 || pBtree->sharable==0 ) return; +#ifndef NDEBUG + { + for(i=0; inMutex; i++){ + assert( pArray->aBtree[i]!=pBtree ); + } + } +#endif + assert( pArray->nMutex>=0 ); + assert( pArray->nMutexaBtree)/sizeof(pArray->aBtree[0])-1 ); + pBt = pBtree->pBt; + for(i=0; inMutex; i++){ + assert( pArray->aBtree[i]!=pBtree ); + if( pArray->aBtree[i]->pBt>pBt ){ + for(j=pArray->nMutex; j>i; j--){ + pArray->aBtree[j] = pArray->aBtree[j-1]; + } + pArray->aBtree[i] = pBtree; + pArray->nMutex++; + return; + } + } + pArray->aBtree[pArray->nMutex++] = pBtree; +} + +/* +** Enter the mutex of every btree in the array. This routine is +** called at the beginning of sqlite3VdbeExec(). The mutexes are +** exited at the end of the same function. +*/ +void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){ + int i; + for(i=0; inMutex; i++){ + Btree *p = pArray->aBtree[i]; + /* Some basic sanity checking */ + assert( i==0 || pArray->aBtree[i-1]->pBtpBt ); + assert( !p->locked || p->wantToLock>0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + p->wantToLock++; + if( !p->locked && p->sharable ){ + sqlite3_mutex_enter(p->pBt->mutex); + p->locked = 1; + } + } +} + +/* +** Leave the mutex of every btree in the group. +*/ +void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ + int i; + for(i=0; inMutex; i++){ + Btree *p = pArray->aBtree[i]; + /* Some basic sanity checking */ + assert( i==0 || pArray->aBtree[i-1]->pBtpBt ); + assert( p->locked || !p->sharable ); + assert( p->wantToLock>0 ); + + /* We should already hold a lock on the database connection */ + assert( sqlite3_mutex_held(p->db->mutex) ); + + p->wantToLock--; + if( p->wantToLock==0 && p->locked ){ + sqlite3_mutex_leave(p->pBt->mutex); + p->locked = 0; + } + } +} + + +#endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/btree.c b/client/src/thirdparty/sqlite-3.4.2/src/btree.c new file mode 100644 index 0000000..dd0e724 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/btree.c @@ -0,0 +1,6943 @@ +/* +** 2004 April 6 +** +** 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. +** +************************************************************************* +** $Id: btree.c,v 1.438 2008/01/31 14:54:44 drh Exp $ +** +** This file implements a external (disk-based) database using BTrees. +** See the header comment on "btreeInt.h" for additional information. +** Including a description of file format and an overview of operation. +*/ +#include "btreeInt.h" + +/* +** The header string that appears at the beginning of every +** SQLite database. +*/ +static const char zMagicHeader[] = SQLITE_FILE_HEADER; + +/* +** Set this global variable to 1 to enable tracing using the TRACE +** macro. +*/ +#if SQLITE_TEST +int sqlite3_btree_trace=0; /* True to enable tracing */ +#endif + + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** A flag to indicate whether or not shared cache is enabled. Also, +** a list of BtShared objects that are eligible for participation +** in shared cache. The variables have file scope during normal builds, +** but the test harness needs to access these variables so we make them +** global for test builds. +*/ +#ifdef SQLITE_TEST +BtShared *sqlite3SharedCacheList = 0; +int sqlite3SharedCacheEnabled = 0; +#else +static BtShared *sqlite3SharedCacheList = 0; +static int sqlite3SharedCacheEnabled = 0; +#endif +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Enable or disable the shared pager and schema features. +** +** This routine has no effect on existing database connections. +** The shared cache setting effects only future calls to +** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2(). +*/ +int sqlite3_enable_shared_cache(int enable){ + sqlite3SharedCacheEnabled = enable; + return SQLITE_OK; +} +#endif + + +/* +** Forward declaration +*/ +static int checkReadLocks(Btree*,Pgno,BtCursor*); + + +#ifdef SQLITE_OMIT_SHARED_CACHE + /* + ** The functions queryTableLock(), lockTable() and unlockAllTables() + ** manipulate entries in the BtShared.pLock linked list used to store + ** shared-cache table level locks. If the library is compiled with the + ** shared-cache feature disabled, then there is only ever one user + ** of each BtShared structure and so this locking is not necessary. + ** So define the lock related functions as no-ops. + */ + #define queryTableLock(a,b,c) SQLITE_OK + #define lockTable(a,b,c) SQLITE_OK + #define unlockAllTables(a) +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Query to see if btree handle p may obtain a lock of type eLock +** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return +** SQLITE_OK if the lock may be obtained (by calling lockTable()), or +** SQLITE_LOCKED if not. +*/ +static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pIter; + + assert( sqlite3BtreeHoldsMutex(p) ); + + /* This is a no-op if the shared-cache is not enabled */ + if( !p->sharable ){ + return SQLITE_OK; + } + + /* If some other connection is holding an exclusive lock, the + ** requested lock may not be obtained. + */ + if( pBt->pExclusive && pBt->pExclusive!=p ){ + return SQLITE_LOCKED; + } + + /* This (along with lockTable()) is where the ReadUncommitted flag is + ** dealt with. If the caller is querying for a read-lock and the flag is + ** set, it is unconditionally granted - even if there are write-locks + ** on the table. If a write-lock is requested, the ReadUncommitted flag + ** is not considered. + ** + ** In function lockTable(), if a read-lock is demanded and the + ** ReadUncommitted flag is set, no entry is added to the locks list + ** (BtShared.pLock). + ** + ** To summarize: If the ReadUncommitted flag is set, then read cursors do + ** not create or respect table locks. The locking procedure for a + ** write-cursor does not change. + */ + if( + !p->db || + 0==(p->db->flags&SQLITE_ReadUncommitted) || + eLock==WRITE_LOCK || + iTab==MASTER_ROOT + ){ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p && pIter->iTable==iTab && + (pIter->eLock!=eLock || eLock!=READ_LOCK) ){ + return SQLITE_LOCKED; + } + } + } + return SQLITE_OK; +} +#endif /* !SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Add a lock on the table with root-page iTable to the shared-btree used +** by Btree handle p. Parameter eLock must be either READ_LOCK or +** WRITE_LOCK. +** +** SQLITE_OK is returned if the lock is added successfully. SQLITE_BUSY and +** SQLITE_NOMEM may also be returned. +*/ +static int lockTable(Btree *p, Pgno iTable, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pLock = 0; + BtLock *pIter; + + assert( sqlite3BtreeHoldsMutex(p) ); + + /* This is a no-op if the shared-cache is not enabled */ + if( !p->sharable ){ + return SQLITE_OK; + } + + assert( SQLITE_OK==queryTableLock(p, iTable, eLock) ); + + /* If the read-uncommitted flag is set and a read-lock is requested, + ** return early without adding an entry to the BtShared.pLock list. See + ** comment in function queryTableLock() for more info on handling + ** the ReadUncommitted flag. + */ + if( + (p->db) && + (p->db->flags&SQLITE_ReadUncommitted) && + (eLock==READ_LOCK) && + iTable!=MASTER_ROOT + ){ + return SQLITE_OK; + } + + /* First search the list for an existing lock on this table. */ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->iTable==iTable && pIter->pBtree==p ){ + pLock = pIter; + break; + } + } + + /* If the above search did not find a BtLock struct associating Btree p + ** with table iTable, allocate one and link it into the list. + */ + if( !pLock ){ + pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock)); + if( !pLock ){ + return SQLITE_NOMEM; + } + pLock->iTable = iTable; + pLock->pBtree = p; + pLock->pNext = pBt->pLock; + pBt->pLock = pLock; + } + + /* Set the BtLock.eLock variable to the maximum of the current lock + ** and the requested lock. This means if a write-lock was already held + ** and a read-lock requested, we don't incorrectly downgrade the lock. + */ + assert( WRITE_LOCK>READ_LOCK ); + if( eLock>pLock->eLock ){ + pLock->eLock = eLock; + } + + return SQLITE_OK; +} +#endif /* !SQLITE_OMIT_SHARED_CACHE */ + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Release all the table locks (locks obtained via calls to the lockTable() +** procedure) held by Btree handle p. +*/ +static void unlockAllTables(Btree *p){ + BtShared *pBt = p->pBt; + BtLock **ppIter = &pBt->pLock; + + assert( sqlite3BtreeHoldsMutex(p) ); + assert( p->sharable || 0==*ppIter ); + + while( *ppIter ){ + BtLock *pLock = *ppIter; + assert( pBt->pExclusive==0 || pBt->pExclusive==pLock->pBtree ); + if( pLock->pBtree==p ){ + *ppIter = pLock->pNext; + sqlite3_free(pLock); + }else{ + ppIter = &pLock->pNext; + } + } + + if( pBt->pExclusive==p ){ + pBt->pExclusive = 0; + } +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +static void releasePage(MemPage *pPage); /* Forward reference */ + +/* +** Verify that the cursor holds a mutex on the BtShared +*/ +#ifndef NDEBUG +static int cursorHoldsMutex(BtCursor *p){ + return sqlite3_mutex_held(p->pBt->mutex); +} +#endif + + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Invalidate the overflow page-list cache for cursor pCur, if any. +*/ +static void invalidateOverflowCache(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + sqlite3_free(pCur->aOverflow); + pCur->aOverflow = 0; +} + +/* +** Invalidate the overflow page-list cache for all cursors opened +** on the shared btree structure pBt. +*/ +static void invalidateAllOverflowCache(BtShared *pBt){ + BtCursor *p; + assert( sqlite3_mutex_held(pBt->mutex) ); + for(p=pBt->pCursor; p; p=p->pNext){ + invalidateOverflowCache(p); + } +} +#else + #define invalidateOverflowCache(x) + #define invalidateAllOverflowCache(x) +#endif + +/* +** Save the current cursor position in the variables BtCursor.nKey +** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. +*/ +static int saveCursorPosition(BtCursor *pCur){ + int rc; + + assert( CURSOR_VALID==pCur->eState ); + assert( 0==pCur->pKey ); + assert( cursorHoldsMutex(pCur) ); + + rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + + /* If this is an intKey table, then the above call to BtreeKeySize() + ** stores the integer key in pCur->nKey. In this case this value is + ** all that is required. Otherwise, if pCur is not open on an intKey + ** table, then malloc space for and store the pCur->nKey bytes of key + ** data. + */ + if( rc==SQLITE_OK && 0==pCur->pPage->intKey){ + void *pKey = sqlite3_malloc(pCur->nKey); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqlite3_free(pKey); + } + }else{ + rc = SQLITE_NOMEM; + } + } + assert( !pCur->pPage->intKey || !pCur->pKey ); + + if( rc==SQLITE_OK ){ + releasePage(pCur->pPage); + pCur->pPage = 0; + pCur->eState = CURSOR_REQUIRESEEK; + } + + invalidateOverflowCache(pCur); + return rc; +} + +/* +** Save the positions of all cursors except pExcept open on the table +** with root-page iRoot. Usually, this is called just before cursor +** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). +*/ +static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pExcept==0 || pExcept->pBt==pBt ); + for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && + p->eState==CURSOR_VALID ){ + int rc = saveCursorPosition(p); + if( SQLITE_OK!=rc ){ + return rc; + } + } + } + return SQLITE_OK; +} + +/* +** Clear the current cursor position. +*/ +static void clearCursorPosition(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + sqlite3_free(pCur->pKey); + pCur->pKey = 0; + pCur->eState = CURSOR_INVALID; +} + +/* +** Restore the cursor to the position it was in (or as close to as possible) +** when saveCursorPosition() was called. Note that this call deletes the +** saved position info stored by saveCursorPosition(), so there can be +** at most one effective restoreOrClearCursorPosition() call after each +** saveCursorPosition(). +** +** If the second argument argument - doSeek - is false, then instead of +** returning the cursor to its saved position, any saved position is deleted +** and the cursor state set to CURSOR_INVALID. +*/ +int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ + int rc; + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState>=CURSOR_REQUIRESEEK ); + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } +#ifndef SQLITE_OMIT_INCRBLOB + if( pCur->isIncrblobHandle ){ + return SQLITE_ABORT; + } +#endif + pCur->eState = CURSOR_INVALID; + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); + if( rc==SQLITE_OK ){ + sqlite3_free(pCur->pKey); + pCur->pKey = 0; + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + } + return rc; +} + +#define restoreOrClearCursorPosition(p) \ + (p->eState>=CURSOR_REQUIRESEEK ? \ + sqlite3BtreeRestoreOrClearCursorPosition(p) : \ + SQLITE_OK) + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Given a page number of a regular database page, return the page +** number for the pointer-map page that contains the entry for the +** input page number. +*/ +static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ + int nPagesPerMapPage, iPtrMap, ret; + assert( sqlite3_mutex_held(pBt->mutex) ); + nPagesPerMapPage = (pBt->usableSize/5)+1; + iPtrMap = (pgno-2)/nPagesPerMapPage; + ret = (iPtrMap*nPagesPerMapPage) + 2; + if( ret==PENDING_BYTE_PAGE(pBt) ){ + ret++; + } + return ret; +} + +/* +** Write an entry into the pointer map. +** +** This routine updates the pointer map entry for page number 'key' +** so that it maps to type 'eType' and parent page number 'pgno'. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ + DbPage *pDbPage; /* The pointer map page */ + u8 *pPtrmap; /* The pointer map data */ + Pgno iPtrmap; /* The pointer map page number */ + int offset; /* Offset in pointer map page */ + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + /* The master-journal page number must never be used as a pointer map page */ + assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); + + assert( pBt->autoVacuum ); + if( key==0 ){ + return SQLITE_CORRUPT_BKPT; + } + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + offset = PTRMAP_PTROFFSET(pBt, key); + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ + TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); + rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK ){ + pPtrmap[offset] = eType; + put4byte(&pPtrmap[offset+1], parent); + } + } + + sqlite3PagerUnref(pDbPage); + return rc; +} + +/* +** Read an entry from the pointer map. +** +** This routine retrieves the pointer map entry for page 'key', writing +** the type and parent page number to *pEType and *pPgno respectively. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ + DbPage *pDbPage; /* The pointer map page */ + int iPtrmap; /* Pointer map page index */ + u8 *pPtrmap; /* Pointer map page data */ + int offset; /* Offset of entry in pointer map */ + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=0 ){ + return rc; + } + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + offset = PTRMAP_PTROFFSET(pBt, key); + assert( pEType!=0 ); + *pEType = pPtrmap[offset]; + if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); + + sqlite3PagerUnref(pDbPage); + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; + return SQLITE_OK; +} + +#endif /* SQLITE_OMIT_AUTOVACUUM */ + +/* +** Given a btree page and a cell index (0 means the first cell on +** the page, 1 means the second cell, and so forth) return a pointer +** to the cell content. +** +** This routine works only for pages that do not contain overflow cells. +*/ +#define findCell(pPage, iCell) \ + ((pPage)->aData + get2byte(&(pPage)->aData[(pPage)->cellOffset+2*(iCell)])) +#ifdef SQLITE_TEST +u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){ + assert( iCell>=0 ); + assert( iCellaData[pPage->hdrOffset+3]) ); + return findCell(pPage, iCell); +} +#endif + +/* +** This a more complex version of sqlite3BtreeFindCell() that works for +** pages that do contain overflow cells. See insert +*/ +static u8 *findOverflowCell(MemPage *pPage, int iCell){ + int i; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + for(i=pPage->nOverflow-1; i>=0; i--){ + int k; + struct _OvflCell *pOvfl; + pOvfl = &pPage->aOvfl[i]; + k = pOvfl->idx; + if( k<=iCell ){ + if( k==iCell ){ + return pOvfl->pCell; + } + iCell--; + } + } + return findCell(pPage, iCell); +} + +/* +** Parse a cell content block and fill in the CellInfo structure. There +** are two versions of this function. sqlite3BtreeParseCell() takes a +** cell index as the second argument and sqlite3BtreeParseCellPtr() +** takes a pointer to the body of the cell as its second argument. +** +** Within this file, the parseCell() macro can be called instead of +** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster. +*/ +void sqlite3BtreeParseCellPtr( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + int n; /* Number bytes in cell content header */ + u32 nPayload; /* Number of bytes of cell payload */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + pInfo->pCell = pCell; + assert( pPage->leaf==0 || pPage->leaf==1 ); + n = pPage->childPtrSize; + assert( n==4-4*pPage->leaf ); + if( pPage->hasData ){ + n += getVarint32(&pCell[n], &nPayload); + }else{ + nPayload = 0; + } + pInfo->nData = nPayload; + if( pPage->intKey ){ + n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); + }else{ + u32 x; + n += getVarint32(&pCell[n], &x); + pInfo->nKey = x; + nPayload += x; + } + pInfo->nPayload = nPayload; + pInfo->nHeader = n; + if( nPayload<=pPage->maxLocal ){ + /* This is the (easy) common case where the entire payload fits + ** on the local page. No overflow is required. + */ + int nSize; /* Total size of cell content in bytes */ + pInfo->nLocal = nPayload; + pInfo->iOverflow = 0; + nSize = nPayload + n; + if( nSize<4 ){ + nSize = 4; /* Minimum cell size is 4 */ + } + pInfo->nSize = nSize; + }else{ + /* If the payload will not fit completely on the local page, we have + ** to decide how much to store locally and how much to spill onto + ** overflow pages. The strategy is to minimize the amount of unused + ** space on overflow pages while keeping the amount of local storage + ** in between minLocal and maxLocal. + ** + ** Warning: changing the way overflow payload is distributed in any + ** way will result in an incompatible file format. + */ + int minLocal; /* Minimum amount of payload held locally */ + int maxLocal; /* Maximum amount of payload held locally */ + int surplus; /* Overflow payload available for local storage */ + + minLocal = pPage->minLocal; + maxLocal = pPage->maxLocal; + surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4); + if( surplus <= maxLocal ){ + pInfo->nLocal = surplus; + }else{ + pInfo->nLocal = minLocal; + } + pInfo->iOverflow = pInfo->nLocal + n; + pInfo->nSize = pInfo->iOverflow + 4; + } +} +#define parseCell(pPage, iCell, pInfo) \ + sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) +void sqlite3BtreeParseCell( + MemPage *pPage, /* Page containing the cell */ + int iCell, /* The cell index. First cell is 0 */ + CellInfo *pInfo /* Fill in this structure */ +){ + parseCell(pPage, iCell, pInfo); +} + +/* +** Compute the total number of bytes that a Cell needs in the cell +** data area of the btree-page. The return number includes the cell +** data header and the local payload, but not any overflow page or +** the space used by the cell pointer. +*/ +#ifndef NDEBUG +static int cellSize(MemPage *pPage, int iCell){ + CellInfo info; + sqlite3BtreeParseCell(pPage, iCell, &info); + return info.nSize; +} +#endif +static int cellSizePtr(MemPage *pPage, u8 *pCell){ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + return info.nSize; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** If the cell pCell, part of page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ + if( pCell ){ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); + if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + Pgno ovfl = get4byte(&pCell[info.iOverflow]); + return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); + } + } + return SQLITE_OK; +} +/* +** If the cell with index iCell on page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static int ptrmapPutOvfl(MemPage *pPage, int iCell){ + u8 *pCell; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pCell = findOverflowCell(pPage, iCell); + return ptrmapPutOvflPtr(pPage, pCell); +} +#endif + + +/* +** Defragment the page given. All Cells are moved to the +** end of the page and all free space is collected into one +** big FreeBlk that occurs in between the header and cell +** pointer array and the cell content area. +*/ +static int defragmentPage(MemPage *pPage){ + int i; /* Loop counter */ + int pc; /* Address of a i-th cell */ + int addr; /* Offset of first byte after cell pointer array */ + int hdr; /* Offset to the page header */ + int size; /* Size of a cell */ + int usableSize; /* Number of usable bytes on a page */ + int cellOffset; /* Offset to the cell pointer array */ + int brk; /* Offset to the cell content area */ + int nCell; /* Number of cells on the page */ + unsigned char *data; /* The page data */ + unsigned char *temp; /* Temp area for cell content */ + + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt!=0 ); + assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + temp = sqlite3PagerTempSpace(pPage->pBt->pPager); + data = pPage->aData; + hdr = pPage->hdrOffset; + cellOffset = pPage->cellOffset; + nCell = pPage->nCell; + assert( nCell==get2byte(&data[hdr+3]) ); + usableSize = pPage->pBt->usableSize; + brk = get2byte(&data[hdr+5]); + memcpy(&temp[brk], &data[brk], usableSize - brk); + brk = usableSize; + for(i=0; ipBt->usableSize ); + size = cellSizePtr(pPage, &temp[pc]); + brk -= size; + memcpy(&data[brk], &temp[pc], size); + put2byte(pAddr, brk); + } + assert( brk>=cellOffset+2*nCell ); + put2byte(&data[hdr+5], brk); + data[hdr+1] = 0; + data[hdr+2] = 0; + data[hdr+7] = 0; + addr = cellOffset+2*nCell; + memset(&data[addr], 0, brk-addr); + return SQLITE_OK; +} + +/* +** Allocate nByte bytes of space on a page. +** +** Return the index into pPage->aData[] of the first byte of +** the new allocation. Or return 0 if there is not enough free +** space on the page to satisfy the allocation request. +** +** If the page contains nBytes of free space but does not contain +** nBytes of contiguous free space, then this routine automatically +** calls defragementPage() to consolidate all free space before +** allocating the new chunk. +*/ +static int allocateSpace(MemPage *pPage, int nByte){ + int addr, pc, hdr; + int size; + int nFrag; + int top; + int nCell; + int cellOffset; + unsigned char *data; + + data = pPage->aData; + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( nByte<4 ) nByte = 4; + if( pPage->nFreenOverflow>0 ) return 0; + pPage->nFree -= nByte; + hdr = pPage->hdrOffset; + + nFrag = data[hdr+7]; + if( nFrag<60 ){ + /* Search the freelist looking for a slot big enough to satisfy the + ** space request. */ + addr = hdr+1; + while( (pc = get2byte(&data[addr]))>0 ){ + size = get2byte(&data[pc+2]); + if( size>=nByte ){ + if( sizecellOffset; + if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){ + if( defragmentPage(pPage) ) return 0; + top = get2byte(&data[hdr+5]); + } + top -= nByte; + assert( cellOffset + 2*nCell <= top ); + put2byte(&data[hdr+5], top); + return top; +} + +/* +** Return a section of the pPage->aData to the freelist. +** The first byte of the new free block is pPage->aDisk[start] +** and the size of the block is "size" bytes. +** +** Most of the effort here is involved in coalesing adjacent +** free blocks into a single big free block. +*/ +static void freeSpace(MemPage *pPage, int start, int size){ + int addr, pbegin, hdr; + unsigned char *data = pPage->aData; + + assert( pPage->pBt!=0 ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); + assert( (start + size)<=pPage->pBt->usableSize ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( size<4 ) size = 4; + +#ifdef SQLITE_SECURE_DELETE + /* Overwrite deleted information with zeros when the SECURE_DELETE + ** option is enabled at compile-time */ + memset(&data[start], 0, size); +#endif + + /* Add the space back into the linked list of freeblocks */ + hdr = pPage->hdrOffset; + addr = hdr + 1; + while( (pbegin = get2byte(&data[addr]))0 ){ + assert( pbegin<=pPage->pBt->usableSize-4 ); + assert( pbegin>addr ); + addr = pbegin; + } + assert( pbegin<=pPage->pBt->usableSize-4 ); + assert( pbegin>addr || pbegin==0 ); + put2byte(&data[addr], start); + put2byte(&data[start], pbegin); + put2byte(&data[start+2], size); + pPage->nFree += size; + + /* Coalesce adjacent free blocks */ + addr = pPage->hdrOffset + 1; + while( (pbegin = get2byte(&data[addr]))>0 ){ + int pnext, psize; + assert( pbegin>addr ); + assert( pbegin<=pPage->pBt->usableSize-4 ); + pnext = get2byte(&data[pbegin]); + psize = get2byte(&data[pbegin+2]); + if( pbegin + psize + 3 >= pnext && pnext>0 ){ + int frag = pnext - (pbegin+psize); + assert( frag<=data[pPage->hdrOffset+7] ); + data[pPage->hdrOffset+7] -= frag; + put2byte(&data[pbegin], get2byte(&data[pnext])); + put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin); + }else{ + addr = pbegin; + } + } + + /* If the cell content area begins with a freeblock, remove it. */ + if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ + int top; + pbegin = get2byte(&data[hdr+1]); + memcpy(&data[hdr+1], &data[pbegin], 2); + top = get2byte(&data[hdr+5]); + put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2])); + } +} + +/* +** Decode the flags byte (the first byte of the header) for a page +** and initialize fields of the MemPage structure accordingly. +*/ +static void decodeFlags(MemPage *pPage, int flagByte){ + BtShared *pBt; /* A copy of pPage->pBt */ + + assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; + pPage->zeroData = (flagByte & PTF_ZERODATA)!=0; + pPage->leaf = (flagByte & PTF_LEAF)!=0; + pPage->childPtrSize = 4*(pPage->leaf==0); + pBt = pPage->pBt; + if( flagByte & PTF_LEAFDATA ){ + pPage->leafData = 1; + pPage->maxLocal = pBt->maxLeaf; + pPage->minLocal = pBt->minLeaf; + }else{ + pPage->leafData = 0; + pPage->maxLocal = pBt->maxLocal; + pPage->minLocal = pBt->minLocal; + } + pPage->hasData = !(pPage->zeroData || (!pPage->leaf && pPage->leafData)); +} + +/* +** Initialize the auxiliary information for a disk block. +** +** The pParent parameter must be a pointer to the MemPage which +** is the parent of the page being initialized. The root of a +** BTree has no parent and so for that page, pParent==NULL. +** +** Return SQLITE_OK on success. If we see that the page does +** not contain a well-formed database page, then return +** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not +** guarantee that the page is well-formed. It only shows that +** we failed to detect any corruption. +*/ +int sqlite3BtreeInitPage( + MemPage *pPage, /* The page to be initialized */ + MemPage *pParent /* The parent. Might be NULL */ +){ + int pc; /* Address of a freeblock within pPage->aData[] */ + int hdr; /* Offset to beginning of page header */ + u8 *data; /* Equal to pPage->aData */ + BtShared *pBt; /* The main btree structure */ + int usableSize; /* Amount of usable space on each page */ + int cellOffset; /* Offset from start of page to first cell pointer */ + int nFree; /* Number of unused bytes on the page */ + int top; /* First byte of the cell content area */ + + pBt = pPage->pBt; + assert( pBt!=0 ); + assert( pParent==0 || pParent->pBt==pBt ); + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); + assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); + if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ + /* The parent page should never change unless the file is corrupt */ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->isInit ) return SQLITE_OK; + if( pPage->pParent==0 && pParent!=0 ){ + pPage->pParent = pParent; + sqlite3PagerRef(pParent->pDbPage); + } + hdr = pPage->hdrOffset; + data = pPage->aData; + decodeFlags(pPage, data[hdr]); + pPage->nOverflow = 0; + pPage->idxShift = 0; + usableSize = pBt->usableSize; + pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; + top = get2byte(&data[hdr+5]); + pPage->nCell = get2byte(&data[hdr+3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){ + /* All pages must have at least one cell, except for root pages */ + return SQLITE_CORRUPT_BKPT; + } + + /* Compute the total free space on the page */ + pc = get2byte(&data[hdr+1]); + nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell); + while( pc>0 ){ + int next, size; + if( pc>usableSize-4 ){ + /* Free block is off the page */ + return SQLITE_CORRUPT_BKPT; + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + if( next>0 && next<=pc+size+3 ){ + /* Free blocks must be in accending order */ + return SQLITE_CORRUPT_BKPT; + } + nFree += size; + pc = next; + } + pPage->nFree = nFree; + if( nFree>=usableSize ){ + /* Free space cannot exceed total page size */ + return SQLITE_CORRUPT_BKPT; + } + + pPage->isInit = 1; + return SQLITE_OK; +} + +/* +** Set up a raw page so that it looks like a database page holding +** no entries. +*/ +static void zeroPage(MemPage *pPage, int flags){ + unsigned char *data = pPage->aData; + BtShared *pBt = pPage->pBt; + int hdr = pPage->hdrOffset; + int first; + + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage) == data ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( sqlite3_mutex_held(pBt->mutex) ); + memset(&data[hdr], 0, pBt->usableSize - hdr); + data[hdr] = flags; + first = hdr + 8 + 4*((flags&PTF_LEAF)==0); + memset(&data[hdr+1], 0, 4); + data[hdr+7] = 0; + put2byte(&data[hdr+5], pBt->usableSize); + pPage->nFree = pBt->usableSize - first; + decodeFlags(pPage, flags); + pPage->hdrOffset = hdr; + pPage->cellOffset = first; + pPage->nOverflow = 0; + pPage->idxShift = 0; + pPage->nCell = 0; + pPage->isInit = 1; +} + +/* +** Get a page from the pager. Initialize the MemPage.pBt and +** MemPage.aData elements if needed. +** +** If the noContent flag is set, it means that we do not care about +** the content of the page at this time. So do not go to the disk +** to fetch the content. Just fill in the content with zeros for now. +** If in the future we call sqlite3PagerWrite() on this page, that +** means we have started to be concerned about content and the disk +** read should occur at that point. +*/ +int sqlite3BtreeGetPage( + BtShared *pBt, /* The btree */ + Pgno pgno, /* Number of the page to fetch */ + MemPage **ppPage, /* Return the page in this parameter */ + int noContent /* Do not load page content if true */ +){ + int rc; + MemPage *pPage; + DbPage *pDbPage; + + assert( sqlite3_mutex_held(pBt->mutex) ); + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); + if( rc ) return rc; + pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage); + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; + pPage->pBt = pBt; + pPage->pgno = pgno; + pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; + *ppPage = pPage; + return SQLITE_OK; +} + +/* +** Get a page from the pager and initialize it. This routine +** is just a convenience wrapper around separate calls to +** sqlite3BtreeGetPage() and sqlite3BtreeInitPage(). +*/ +static int getAndInitPage( + BtShared *pBt, /* The database file */ + Pgno pgno, /* Number of the page to get */ + MemPage **ppPage, /* Write the page pointer here */ + MemPage *pParent /* Parent of the page */ +){ + int rc; + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } + rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); + if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ + rc = sqlite3BtreeInitPage(*ppPage, pParent); + } + return rc; +} + +/* +** Release a MemPage. This should be called once for each prior +** call to sqlite3BtreeGetPage. +*/ +static void releasePage(MemPage *pPage){ + if( pPage ){ + assert( pPage->aData ); + assert( pPage->pBt ); + assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); + assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3PagerUnref(pPage->pDbPage); + } +} + +/* +** This routine is called when the reference count for a page +** reaches zero. We need to unref the pParent pointer when that +** happens. +*/ +static void pageDestructor(DbPage *pData, int pageSize){ + MemPage *pPage; + assert( (pageSize & 7)==0 ); + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->pParent ){ + MemPage *pParent = pPage->pParent; + assert( pParent->pBt==pPage->pBt ); + pPage->pParent = 0; + releasePage(pParent); + } + pPage->isInit = 0; +} + +/* +** During a rollback, when the pager reloads information into the cache +** so that the cache is restored to its original state at the start of +** the transaction, for each page restored this routine is called. +** +** This routine needs to reset the extra data section at the end of the +** page to agree with the restored data. +*/ +static void pageReinit(DbPage *pData, int pageSize){ + MemPage *pPage; + assert( (pageSize & 7)==0 ); + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + if( pPage->isInit ){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pPage->isInit = 0; + sqlite3BtreeInitPage(pPage, pPage->pParent); + } +} + +/* +** Invoke the busy handler for a btree. +*/ +static int sqlite3BtreeInvokeBusyHandler(void *pArg, int n){ + BtShared *pBt = (BtShared*)pArg; + assert( pBt->db ); + assert( sqlite3_mutex_held(pBt->db->mutex) ); + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); +} + +/* +** Open a database file. +** +** zFilename is the name of the database file. If zFilename is NULL +** a new database with a random name is created. This randomly named +** database file will be deleted when sqlite3BtreeClose() is called. +** If zFilename is ":memory:" then an in-memory database is created +** that is automatically destroyed when it is closed. +*/ +int sqlite3BtreeOpen( + const char *zFilename, /* Name of the file containing the BTree database */ + sqlite3 *db, /* Associated database handle */ + Btree **ppBtree, /* Pointer to new Btree object written here */ + int flags, /* Options */ + int vfsFlags /* Flags passed through to sqlite3_vfs.xOpen() */ +){ + sqlite3_vfs *pVfs; /* The VFS to use for this btree */ + BtShared *pBt = 0; /* Shared part of btree structure */ + Btree *p; /* Handle to return */ + int rc = SQLITE_OK; + int nReserve; + unsigned char zDbHeader[100]; + + /* Set the variable isMemdb to true for an in-memory database, or + ** false for a file-based database. This symbol is only required if + ** either of the shared-data or autovacuum features are compiled + ** into the library. + */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) + #ifdef SQLITE_OMIT_MEMORYDB + const int isMemdb = 0; + #else + const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); + #endif +#endif + + assert( db!=0 ); + assert( sqlite3_mutex_held(db->mutex) ); + + pVfs = db->pVfs; + p = sqlite3MallocZero(sizeof(Btree)); + if( !p ){ + return SQLITE_NOMEM; + } + p->inTrans = TRANS_NONE; + p->db = db; + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* + ** If this Btree is a candidate for shared cache, try to find an + ** existing BtShared object that we can share with + */ + if( (flags & BTREE_PRIVATE)==0 + && isMemdb==0 + && (db->flags & SQLITE_Vtab)==0 + && zFilename && zFilename[0] + ){ + if( sqlite3SharedCacheEnabled ){ + int nFullPathname = pVfs->mxPathname+1; + char *zFullPathname = (char *)sqlite3_malloc(nFullPathname); + sqlite3_mutex *mutexShared; + p->sharable = 1; + if( db ){ + db->flags |= SQLITE_SharedCache; + } + if( !zFullPathname ){ + sqlite3_free(p); + return SQLITE_NOMEM; + } + sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); + mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(mutexShared); + for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){ + assert( pBt->nRef>0 ); + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) + && sqlite3PagerVfs(pBt->pPager)==pVfs ){ + p->pBt = pBt; + pBt->nRef++; + break; + } + } + sqlite3_mutex_leave(mutexShared); + sqlite3_free(zFullPathname); + } +#ifdef SQLITE_DEBUG + else{ + /* In debug mode, we mark all persistent databases as sharable + ** even when they are not. This exercises the locking code and + ** gives more opportunity for asserts(sqlite3_mutex_held()) + ** statements to find locking problems. + */ + p->sharable = 1; + } +#endif + } +#endif + if( pBt==0 ){ + /* + ** The following asserts make sure that structures used by the btree are + ** 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(u32)==4 ); + assert( sizeof(u16)==2 ); + assert( sizeof(Pgno)==4 ); + + pBt = sqlite3MallocZero( sizeof(*pBt) ); + if( pBt==0 ){ + rc = SQLITE_NOMEM; + goto btree_open_out; + } + pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler; + pBt->busyHdr.pArg = pBt; + rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, + EXTRA_SIZE, flags, vfsFlags); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); + } + if( rc!=SQLITE_OK ){ + goto btree_open_out; + } + sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr); + p->pBt = pBt; + + sqlite3PagerSetDestructor(pBt->pPager, pageDestructor); + sqlite3PagerSetReiniter(pBt->pPager, pageReinit); + pBt->pCursor = 0; + pBt->pPage1 = 0; + pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); + pBt->pageSize = get2byte(&zDbHeader[16]); + if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE + || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ + pBt->pageSize = 0; + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + pBt->maxEmbedFrac = 64; /* 25% */ + pBt->minEmbedFrac = 32; /* 12.5% */ + pBt->minLeafFrac = 32; /* 12.5% */ +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the magic name ":memory:" will create an in-memory database, then + ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if + ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if + ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a + ** regular file-name. In this case the auto-vacuum applies as per normal. + */ + if( zFilename && !isMemdb ){ + pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0); + pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0); + } +#endif + nReserve = 0; + }else{ + nReserve = zDbHeader[20]; + pBt->maxEmbedFrac = zDbHeader[21]; + pBt->minEmbedFrac = zDbHeader[22]; + pBt->minLeafFrac = zDbHeader[23]; + pBt->pageSizeFixed = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); +#endif + } + pBt->usableSize = pBt->pageSize - nReserve; + assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ + sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* Add the new BtShared object to the linked list sharable BtShareds. + */ + if( p->sharable ){ + sqlite3_mutex *mutexShared; + pBt->nRef = 1; + mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + if( SQLITE_THREADSAFE ){ + pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pBt->mutex==0 ){ + rc = SQLITE_NOMEM; + db->mallocFailed = 0; + goto btree_open_out; + } + } + sqlite3_mutex_enter(mutexShared); + pBt->pNext = sqlite3SharedCacheList; + sqlite3SharedCacheList = pBt; + sqlite3_mutex_leave(mutexShared); + } +#endif + } + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* If the new Btree uses a sharable pBtShared, then link the new + ** Btree into the list of all sharable Btrees for the same connection. + ** The list is kept in ascending order by pBt address. + */ + if( p->sharable ){ + int i; + Btree *pSib; + for(i=0; inDb; i++){ + if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){ + while( pSib->pPrev ){ pSib = pSib->pPrev; } + if( p->pBtpBt ){ + p->pNext = pSib; + p->pPrev = 0; + pSib->pPrev = p; + }else{ + while( pSib->pNext && pSib->pNext->pBtpBt ){ + pSib = pSib->pNext; + } + p->pNext = pSib->pNext; + p->pPrev = pSib; + if( p->pNext ){ + p->pNext->pPrev = p; + } + pSib->pNext = p; + } + break; + } + } + } +#endif + *ppBtree = p; + +btree_open_out: + if( rc!=SQLITE_OK ){ + if( pBt && pBt->pPager ){ + sqlite3PagerClose(pBt->pPager); + } + sqlite3_free(pBt); + sqlite3_free(p); + *ppBtree = 0; + } + return rc; +} + +/* +** Decrement the BtShared.nRef counter. When it reaches zero, +** remove the BtShared structure from the sharing list. Return +** true if the BtShared.nRef counter reaches zero and return +** false if it is still positive. +*/ +static int removeFromSharingList(BtShared *pBt){ +#ifndef SQLITE_OMIT_SHARED_CACHE + sqlite3_mutex *pMaster; + BtShared *pList; + int removed = 0; + + assert( sqlite3_mutex_notheld(pBt->mutex) ); + pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(pMaster); + pBt->nRef--; + if( pBt->nRef<=0 ){ + if( sqlite3SharedCacheList==pBt ){ + sqlite3SharedCacheList = pBt->pNext; + }else{ + pList = sqlite3SharedCacheList; + while( pList && pList->pNext!=pBt ){ + pList=pList->pNext; + } + if( pList ){ + pList->pNext = pBt->pNext; + } + } + if( SQLITE_THREADSAFE ){ + sqlite3_mutex_free(pBt->mutex); + } + removed = 1; + } + sqlite3_mutex_leave(pMaster); + return removed; +#else + return 1; +#endif +} + +/* +** Close an open database and invalidate all cursors. +*/ +int sqlite3BtreeClose(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCur; + + /* Close all cursors opened via this handle. */ + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + pBt->db = p->db; + pCur = pBt->pCursor; + while( pCur ){ + BtCursor *pTmp = pCur; + pCur = pCur->pNext; + if( pTmp->pBtree==p ){ + sqlite3BtreeCloseCursor(pTmp); + } + } + + /* Rollback any active transaction and free the handle structure. + ** The call to sqlite3BtreeRollback() drops any table-locks held by + ** this handle. + */ + sqlite3BtreeRollback(p); + sqlite3BtreeLeave(p); + + /* If there are still other outstanding references to the shared-btree + ** structure, return now. The remainder of this procedure cleans + ** up the shared-btree. + */ + assert( p->wantToLock==0 && p->locked==0 ); + if( !p->sharable || removeFromSharingList(pBt) ){ + /* The pBt is no longer on the sharing list, so we can access + ** it without having to hold the mutex. + ** + ** Clean out and delete the BtShared object. + */ + assert( !pBt->pCursor ); + sqlite3PagerClose(pBt->pPager); + if( pBt->xFreeSchema && pBt->pSchema ){ + pBt->xFreeSchema(pBt->pSchema); + } + sqlite3_free(pBt->pSchema); + sqlite3_free(pBt); + } + +#ifndef SQLITE_OMIT_SHARED_CACHE + assert( p->wantToLock==0 ); + assert( p->locked==0 ); + if( p->pPrev ) p->pPrev->pNext = p->pNext; + if( p->pNext ) p->pNext->pPrev = p->pPrev; +#endif + + sqlite3_free(p); + return SQLITE_OK; +} + +/* +** Change the limit on the number of pages allowed in the cache. +** +** The maximum number of cache pages is set to the absolute +** value of mxPage. If mxPage is negative, the pager will +** operate asynchronously - it will not stop to do fsync()s +** to insure data is written to the disk surface before +** continuing. Transactions still work if synchronous is off, +** and the database cannot be corrupted if this program +** crashes. But if the operating system crashes or there is +** an abrupt power failure when synchronous is off, the database +** could be left in an inconsistent and unrecoverable state. +** Synchronous is on by default so database corruption is not +** normally a worry. +*/ +int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetCachesize(pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} + +/* +** Change the way data is synced to disk in order to increase or decrease +** how well the database resists damage due to OS crashes and power +** failures. Level 1 is the same as asynchronous (no syncs() occur and +** there is a high probability of damage) Level 2 is the default. There +** is a very low but non-zero probability of damage. Level 3 reduces the +** probability of damage to near zero but with a write performance reduction. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ + BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} +#endif + +/* +** Return TRUE if the given btree is set to safety level 1. In other +** words, return TRUE if no sync() occurs on the disk files. +*/ +int sqlite3BtreeSyncDisabled(Btree *p){ + BtShared *pBt = p->pBt; + int rc; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + assert( pBt && pBt->pPager ); + rc = sqlite3PagerNosync(pBt->pPager); + sqlite3BtreeLeave(p); + return rc; +} + +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) +/* +** Change the default pages size and the number of reserved bytes per page. +** +** The page size must be a power of 2 between 512 and 65536. If the page +** size supplied does not meet this constraint then the page size is not +** changed. +** +** Page sizes are constrained to be a power of two so that the region +** of the database file used for locking (beginning at PENDING_BYTE, +** the first byte past the 1GB boundary, 0x40000000) needs to occur +** at the beginning of a page. +** +** If parameter nReserve is less than zero, then the number of reserved +** bytes per page is left unchanged. +*/ +int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + if( pBt->pageSizeFixed ){ + sqlite3BtreeLeave(p); + return SQLITE_READONLY; + } + if( nReserve<0 ){ + nReserve = pBt->pageSize - pBt->usableSize; + } + if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && + ((pageSize-1)&pageSize)==0 ){ + assert( (pageSize & 7)==0 ); + assert( !pBt->pPage1 && !pBt->pCursor ); + pBt->pageSize = pageSize; + rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize); + } + pBt->usableSize = pBt->pageSize - nReserve; + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Return the currently defined page size +*/ +int sqlite3BtreeGetPageSize(Btree *p){ + return p->pBt->pageSize; +} +int sqlite3BtreeGetReserve(Btree *p){ + int n; + sqlite3BtreeEnter(p); + n = p->pBt->pageSize - p->pBt->usableSize; + 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. +** Regardless of the value of mxPage, return the maximum page count. +*/ +int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ + int n; + sqlite3BtreeEnter(p); + n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); + sqlite3BtreeLeave(p); + return n; +} +#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ + +/* +** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' +** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it +** is disabled. The default value for the auto-vacuum property is +** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. +*/ +int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return SQLITE_READONLY; +#else + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + int av = (autoVacuum?1:0); + + sqlite3BtreeEnter(p); + if( pBt->pageSizeFixed && av!=pBt->autoVacuum ){ + rc = SQLITE_READONLY; + }else{ + pBt->autoVacuum = av; + } + sqlite3BtreeLeave(p); + return rc; +#endif +} + +/* +** Return the value of the 'auto-vacuum' property. If auto-vacuum is +** enabled 1 is returned. Otherwise 0. +*/ +int sqlite3BtreeGetAutoVacuum(Btree *p){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return BTREE_AUTOVACUUM_NONE; +#else + int rc; + sqlite3BtreeEnter(p); + rc = ( + (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE: + (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL: + BTREE_AUTOVACUUM_INCR + ); + sqlite3BtreeLeave(p); + return rc; +#endif +} + + +/* +** Get a reference to pPage1 of the database file. This will +** also acquire a readlock on that file. +** +** SQLITE_OK is returned on success. If the file is not a +** well-formed database file, then SQLITE_CORRUPT is returned. +** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM +** is returned if we run out of memory. +*/ +static int lockBtree(BtShared *pBt){ + int rc, pageSize; + MemPage *pPage1; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pBt->pPage1 ) return SQLITE_OK; + rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); + if( rc!=SQLITE_OK ) return rc; + + + /* Do some checking to help insure the file we opened really is + ** a valid database file. + */ + rc = SQLITE_NOTADB; + if( sqlite3PagerPagecount(pBt->pPager)>0 ){ + u8 *page1 = pPage1->aData; + if( memcmp(page1, zMagicHeader, 16)!=0 ){ + goto page1_init_failed; + } + if( page1[18]>1 ){ + pBt->readOnly = 1; + } + if( page1[19]>1 ){ + goto page1_init_failed; + } + pageSize = get2byte(&page1[16]); + if( ((pageSize-1)&pageSize)!=0 || pageSize<512 || + (SQLITE_MAX_PAGE_SIZE<32768 && pageSize>SQLITE_MAX_PAGE_SIZE) + ){ + goto page1_init_failed; + } + assert( (pageSize & 7)==0 ); + pBt->pageSize = pageSize; + pBt->usableSize = pageSize - page1[20]; + if( pBt->usableSize<500 ){ + goto page1_init_failed; + } + pBt->maxEmbedFrac = page1[21]; + pBt->minEmbedFrac = page1[22]; + pBt->minLeafFrac = page1[23]; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); +#endif + } + + /* maxLocal is the maximum amount of payload to store locally for + ** a cell. Make sure it is small enough so that at least minFanout + ** cells can will fit on one page. We assume a 10-byte page header. + ** Besides the payload, the cell must store: + ** 2-byte pointer to the cell + ** 4-byte child pointer + ** 9-byte nKey value + ** 4-byte nData value + ** 4-byte overflow page pointer + ** So a cell consists of a 2-byte poiner, a header which is as much as + ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow + ** page pointer. + */ + pBt->maxLocal = (pBt->usableSize-12)*pBt->maxEmbedFrac/255 - 23; + pBt->minLocal = (pBt->usableSize-12)*pBt->minEmbedFrac/255 - 23; + pBt->maxLeaf = pBt->usableSize - 35; + pBt->minLeaf = (pBt->usableSize-12)*pBt->minLeafFrac/255 - 23; + if( pBt->minLocal>pBt->maxLocal || pBt->maxLocal<0 ){ + goto page1_init_failed; + } + assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); + pBt->pPage1 = pPage1; + return SQLITE_OK; + +page1_init_failed: + releasePage(pPage1); + pBt->pPage1 = 0; + return rc; +} + +/* +** This routine works like lockBtree() except that it also invokes the +** busy callback if there is lock contention. +*/ +static int lockBtreeWithRetry(Btree *pRef){ + int rc = SQLITE_OK; + + assert( sqlite3BtreeHoldsMutex(pRef) ); + if( pRef->inTrans==TRANS_NONE ){ + u8 inTransaction = pRef->pBt->inTransaction; + btreeIntegrity(pRef); + rc = sqlite3BtreeBeginTrans(pRef, 0); + pRef->pBt->inTransaction = inTransaction; + pRef->inTrans = TRANS_NONE; + if( rc==SQLITE_OK ){ + pRef->pBt->nTransaction--; + } + btreeIntegrity(pRef); + } + return rc; +} + + +/* +** If there are no outstanding cursors and we are not in the middle +** of a transaction but there is a read lock on the database, then +** this routine unrefs the first page of the database file which +** has the effect of releasing the read lock. +** +** If there are any outstanding cursors, this routine is a no-op. +** +** If there is a transaction in progress, this routine is a no-op. +*/ +static void unlockBtreeIfUnused(BtShared *pBt){ + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ + if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ + assert( pBt->pPage1->aData ); +#if 0 + if( pBt->pPage1->aData==0 ){ + MemPage *pPage = pBt->pPage1; + pPage->aData = sqlite3PagerGetData(pPage->pDbPage); + pPage->pBt = pBt; + pPage->pgno = 1; + } +#endif + releasePage(pBt->pPage1); + } + pBt->pPage1 = 0; + pBt->inStmt = 0; + } +} + +/* +** Create a new database by initializing the first page of the +** file. +*/ +static int newDatabase(BtShared *pBt){ + MemPage *pP1; + unsigned char *data; + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK; + pP1 = pBt->pPage1; + assert( pP1!=0 ); + data = pP1->aData; + rc = sqlite3PagerWrite(pP1->pDbPage); + if( rc ) return rc; + memcpy(data, zMagicHeader, sizeof(zMagicHeader)); + assert( sizeof(zMagicHeader)==16 ); + put2byte(&data[16], pBt->pageSize); + data[18] = 1; + data[19] = 1; + data[20] = pBt->pageSize - pBt->usableSize; + data[21] = pBt->maxEmbedFrac; + data[22] = pBt->minEmbedFrac; + data[23] = pBt->minLeafFrac; + memset(&data[24], 0, 100-24); + zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA ); + pBt->pageSizeFixed = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 ); + assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 ); + put4byte(&data[36 + 4*4], pBt->autoVacuum); + put4byte(&data[36 + 7*4], pBt->incrVacuum); +#endif + return SQLITE_OK; +} + +/* +** Attempt to start a new transaction. A write-transaction +** is started if the second argument is nonzero, otherwise a read- +** transaction. If the second argument is 2 or more and exclusive +** transaction is started, meaning that no other process is allowed +** to access the database. A preexisting transaction may not be +** upgraded to exclusive by calling this routine a second time - the +** exclusivity flag only works for a new transaction. +** +** A write-transaction must be started before attempting any +** changes to the database. None of the following routines +** will work unless a transaction is started first: +** +** sqlite3BtreeCreateTable() +** sqlite3BtreeCreateIndex() +** sqlite3BtreeClearTable() +** sqlite3BtreeDropTable() +** sqlite3BtreeInsert() +** sqlite3BtreeDelete() +** sqlite3BtreeUpdateMeta() +** +** If an initial attempt to acquire the lock fails because of lock contention +** and the database was previously unlocked, then invoke the busy handler +** if there is one. But if there was previously a read-lock, do not +** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is +** returned when there is already a read-lock in order to avoid a deadlock. +** +** Suppose there are two processes A and B. A has a read lock and B has +** a reserved lock. B tries to promote to exclusive but is blocked because +** of A's read lock. A tries to promote to reserved but is blocked by B. +** One or the other of the two processes must give way or there can be +** no progress. By returning SQLITE_BUSY and not invoking the busy callback +** when A already has a read lock, we encourage A to give up and let B +** proceed. +*/ +int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + btreeIntegrity(p); + + /* If the btree is already in a write-transaction, or it + ** is already in a read-transaction and a read-transaction + ** is requested, this is a no-op. + */ + if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ + goto trans_begun; + } + + /* Write transactions are not possible on a read-only database */ + if( pBt->readOnly && wrflag ){ + rc = SQLITE_READONLY; + goto trans_begun; + } + + /* If another database handle has already opened a write transaction + ** on this shared-btree structure and a second write transaction is + ** requested, return SQLITE_BUSY. + */ + if( pBt->inTransaction==TRANS_WRITE && wrflag ){ + rc = SQLITE_BUSY; + goto trans_begun; + } + +#ifndef SQLITE_OMIT_SHARED_CACHE + if( wrflag>1 ){ + BtLock *pIter; + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p ){ + rc = SQLITE_BUSY; + goto trans_begun; + } + } + } +#endif + + do { + if( pBt->pPage1==0 ){ + rc = lockBtree(pBt); + } + + if( rc==SQLITE_OK && wrflag ){ + if( pBt->readOnly ){ + rc = SQLITE_READONLY; + }else{ + rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1); + if( rc==SQLITE_OK ){ + rc = newDatabase(pBt); + } + } + } + + if( rc==SQLITE_OK ){ + if( wrflag ) pBt->inStmt = 0; + }else{ + unlockBtreeIfUnused(pBt); + } + }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && + sqlite3BtreeInvokeBusyHandler(pBt, 0) ); + + if( rc==SQLITE_OK ){ + if( p->inTrans==TRANS_NONE ){ + pBt->nTransaction++; + } + p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); + if( p->inTrans>pBt->inTransaction ){ + pBt->inTransaction = p->inTrans; + } +#ifndef SQLITE_OMIT_SHARED_CACHE + if( wrflag>1 ){ + assert( !pBt->pExclusive ); + pBt->pExclusive = p; + } +#endif + } + + +trans_begun: + btreeIntegrity(p); + sqlite3BtreeLeave(p); + return rc; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM + +/* +** Set the pointer-map entries for all children of page pPage. Also, if +** pPage contains cells that point to overflow pages, set the pointer +** map entries for the overflow pages as well. +*/ +static int setChildPtrmaps(MemPage *pPage){ + int i; /* Counter variable */ + int nCell; /* Number of cells in page pPage */ + int rc; /* Return code */ + BtShared *pBt = pPage->pBt; + int isInitOrig = pPage->isInit; + Pgno pgno = pPage->pgno; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + rc = sqlite3BtreeInitPage(pPage, pPage->pParent); + if( rc!=SQLITE_OK ){ + goto set_child_ptrmaps_out; + } + nCell = pPage->nCell; + + for(i=0; ileaf ){ + Pgno childPgno = get4byte(pCell); + rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out; + } + } + + if( !pPage->leaf ){ + Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + } + +set_child_ptrmaps_out: + pPage->isInit = isInitOrig; + return rc; +} + +/* +** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow +** page, is a pointer to page iFrom. Modify this pointer so that it points to +** iTo. Parameter eType describes the type of pointer to be modified, as +** follows: +** +** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child +** page of pPage. +** +** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow +** page pointed to by one of the cells on pPage. +** +** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next +** overflow page in the list. +*/ +static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( eType==PTRMAP_OVERFLOW2 ){ + /* The pointer is always the first 4 bytes of the page in this case. */ + if( get4byte(pPage->aData)!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(pPage->aData, iTo); + }else{ + int isInitOrig = pPage->isInit; + int i; + int nCell; + + sqlite3BtreeInitPage(pPage, 0); + nCell = pPage->nCell; + + for(i=0; iaData[pPage->hdrOffset+8])!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); + } + + pPage->isInit = isInitOrig; + } + return SQLITE_OK; +} + + +/* +** Move the open database page pDbPage to location iFreePage in the +** database. The pDbPage reference remains valid. +*/ +static int relocatePage( + BtShared *pBt, /* Btree */ + MemPage *pDbPage, /* Open page to move */ + u8 eType, /* Pointer map 'type' entry for pDbPage */ + Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ + Pgno iFreePage /* The location to move pDbPage to */ +){ + MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ + Pgno iDbPage = pDbPage->pgno; + Pager *pPager = pBt->pPager; + int rc; + + assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || + eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pDbPage->pBt==pBt ); + + /* Move page iDbPage from its current location to page number iFreePage */ + TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", + iDbPage, iFreePage, iPtrPage, eType)); + rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage); + if( rc!=SQLITE_OK ){ + return rc; + } + pDbPage->pgno = iFreePage; + + /* If pDbPage was a btree-page, then it may have child pages and/or cells + ** that point to overflow pages. The pointer map entries for all these + ** pages need to be changed. + ** + ** If pDbPage is an overflow page, then the first 4 bytes may store a + ** pointer to a subsequent overflow page. If this is the case, then + ** the pointer map needs to be updated for the subsequent overflow page. + */ + if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){ + rc = setChildPtrmaps(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + Pgno nextOvfl = get4byte(pDbPage->aData); + if( nextOvfl!=0 ){ + rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + /* Fix the database pointer on page iPtrPage that pointed at iDbPage so + ** that it points at iFreePage. Also fix the pointer map entry for + ** iPtrPage. + */ + if( eType!=PTRMAP_ROOTPAGE ){ + rc = sqlite3BtreeGetPage(pBt, iPtrPage, &pPtrPage, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pPtrPage->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pPtrPage); + return rc; + } + rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); + releasePage(pPtrPage); + if( rc==SQLITE_OK ){ + rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); + } + } + return rc; +} + +/* Forward declaration required by incrVacuumStep(). */ +static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); + +/* +** Perform a single step of an incremental-vacuum. If successful, +** return SQLITE_OK. If there is no work to do (and therefore no +** point in calling this function again), return SQLITE_DONE. +** +** More specificly, this function attempts to re-organize the +** database so that the last page of the file currently in use +** is no longer in use. +** +** If the nFin parameter is non-zero, the implementation assumes +** that the caller will keep calling incrVacuumStep() until +** it returns SQLITE_DONE or an error, and that nFin is the +** number of pages the database file will contain after this +** process is complete. +*/ +static int incrVacuumStep(BtShared *pBt, Pgno nFin){ + Pgno iLastPg; /* Last page in the database */ + Pgno nFreeList; /* Number of pages still on the free-list */ + + assert( sqlite3_mutex_held(pBt->mutex) ); + iLastPg = pBt->nTrunc; + if( iLastPg==0 ){ + iLastPg = sqlite3PagerPagecount(pBt->pPager); + } + + if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ + int rc; + u8 eType; + Pgno iPtrPage; + + nFreeList = get4byte(&pBt->pPage1->aData[36]); + if( nFreeList==0 || nFin==iLastPg ){ + return SQLITE_DONE; + } + + rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_ROOTPAGE ){ + return SQLITE_CORRUPT_BKPT; + } + + if( eType==PTRMAP_FREEPAGE ){ + if( nFin==0 ){ + /* Remove the page from the files free-list. This is not required + ** if nFin is non-zero. In that case, the free-list will be + ** truncated to zero after this function returns, so it doesn't + ** matter if it still contains some garbage entries. + */ + Pgno iFreePg; + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( iFreePg==iLastPg ); + releasePage(pFreePg); + } + } else { + Pgno iFreePg; /* Index of free page to move pLastPg to */ + MemPage *pLastPg; + + rc = sqlite3BtreeGetPage(pBt, iLastPg, &pLastPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* If nFin is zero, this loop runs exactly once and page pLastPg + ** is swapped with the first free page pulled off the free list. + ** + ** On the other hand, if nFin is greater than zero, then keep + ** looping until a free-page located within the first nFin pages + ** of the file is found. + */ + do { + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0); + if( rc!=SQLITE_OK ){ + releasePage(pLastPg); + return rc; + } + releasePage(pFreePg); + }while( nFin!=0 && iFreePg>nFin ); + assert( iFreePgpDbPage); + if( rc==SQLITE_OK ){ + rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg); + } + releasePage(pLastPg); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + pBt->nTrunc = iLastPg - 1; + while( pBt->nTrunc==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, pBt->nTrunc) ){ + pBt->nTrunc--; + } + return SQLITE_OK; +} + +/* +** A write-transaction must be opened before calling this function. +** It performs a single unit of work towards an incremental vacuum. +** +** If the incremental vacuum is finished after this function has run, +** SQLITE_DONE is returned. If it is not finished, but no error occured, +** SQLITE_OK is returned. Otherwise an SQLite error code. +*/ +int sqlite3BtreeIncrVacuum(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); + if( !pBt->autoVacuum ){ + rc = SQLITE_DONE; + }else{ + invalidateAllOverflowCache(pBt); + rc = incrVacuumStep(pBt, 0); + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** This routine is called prior to sqlite3PagerCommit when a transaction +** is commited for an auto-vacuum database. +** +** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages +** the database file should be truncated to during the commit process. +** i.e. the database has been reorganized so that only the first *pnTrunc +** pages are in use. +*/ +static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ + int rc = SQLITE_OK; + Pager *pPager = pBt->pPager; +#ifndef NDEBUG + int nRef = sqlite3PagerRefcount(pPager); +#endif + + assert( sqlite3_mutex_held(pBt->mutex) ); + invalidateAllOverflowCache(pBt); + assert(pBt->autoVacuum); + if( !pBt->incrVacuum ){ + Pgno nFin = 0; + + if( pBt->nTrunc==0 ){ + Pgno nFree; + Pgno nPtrmap; + const int pgsz = pBt->pageSize; + Pgno nOrig = sqlite3PagerPagecount(pBt->pPager); + + if( PTRMAP_ISPAGE(pBt, nOrig) ){ + return SQLITE_CORRUPT_BKPT; + } + if( nOrig==PENDING_BYTE_PAGE(pBt) ){ + nOrig--; + } + nFree = get4byte(&pBt->pPage1->aData[36]); + nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+pgsz/5)/(pgsz/5); + nFin = nOrig - nFree - nPtrmap; + if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<=PENDING_BYTE_PAGE(pBt) ){ + nFin--; + } + while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ + nFin--; + } + } + + while( rc==SQLITE_OK ){ + rc = incrVacuumStep(pBt, nFin); + } + if( rc==SQLITE_DONE ){ + assert(nFin==0 || pBt->nTrunc==0 || nFin<=pBt->nTrunc); + rc = SQLITE_OK; + if( pBt->nTrunc ){ + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + put4byte(&pBt->pPage1->aData[32], 0); + put4byte(&pBt->pPage1->aData[36], 0); + pBt->nTrunc = nFin; + } + } + if( rc!=SQLITE_OK ){ + sqlite3PagerRollback(pPager); + } + } + + if( rc==SQLITE_OK ){ + *pnTrunc = pBt->nTrunc; + pBt->nTrunc = 0; + } + assert( nRef==sqlite3PagerRefcount(pPager) ); + return rc; +} + +#endif + +/* +** This routine does the first phase of a two-phase commit. This routine +** causes a rollback journal to be created (if it does not already exist) +** and populated with enough information so that if a power loss occurs +** the database can be restored to its original state by playing back +** the journal. Then the contents of the journal are flushed out to +** the disk. After the journal is safely on oxide, the changes to the +** database are written into the database file and flushed to oxide. +** At the end of this call, the rollback journal still exists on the +** disk and we are still holding all locks, so the transaction has not +** committed. See sqlite3BtreeCommit() for the second phase of the +** commit process. +** +** This call is a no-op if no write-transaction is currently active on pBt. +** +** Otherwise, sync the database file for the btree pBt. zMaster points to +** the name of a master journal file that should be written into the +** individual journal file, or is NULL, indicating no master journal file +** (single database transaction). +** +** When this is called, the master journal should already have been +** created, populated with this journal pointer and synced to disk. +** +** Once this is routine has returned, the only thing required to commit +** the write-transaction for this database file is to delete the journal. +*/ +int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; + Pgno nTrunc = 0; + sqlite3BtreeEnter(p); + pBt->db = p->db; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + rc = autoVacuumCommit(pBt, &nTrunc); + if( rc!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return rc; + } + } +#endif + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc); + sqlite3BtreeLeave(p); + } + return rc; +} + +/* +** Commit the transaction currently in progress. +** +** This routine implements the second phase of a 2-phase commit. The +** sqlite3BtreeSync() routine does the first phase and should be invoked +** prior to calling this routine. The sqlite3BtreeSync() routine did +** all the work of writing information out to disk and flushing the +** contents so that they are written onto the disk platter. All this +** routine has to do is delete or truncate the rollback journal +** (which causes the transaction to commit) and drop locks. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +int sqlite3BtreeCommitPhaseTwo(Btree *p){ + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + btreeIntegrity(p); + + /* If the handle has a write-transaction open, commit the shared-btrees + ** transaction and set the shared state to TRANS_READ. + */ + if( p->inTrans==TRANS_WRITE ){ + int rc; + assert( pBt->inTransaction==TRANS_WRITE ); + assert( pBt->nTransaction>0 ); + rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); + if( rc!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return rc; + } + pBt->inTransaction = TRANS_READ; + pBt->inStmt = 0; + } + unlockAllTables(p); + + /* If the handle has any kind of transaction open, decrement the transaction + ** count of the shared btree. If the transaction count reaches 0, set + ** the shared state to TRANS_NONE. The unlockBtreeIfUnused() call below + ** will unlock the pager. + */ + if( p->inTrans!=TRANS_NONE ){ + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + /* Set the handles current transaction state to TRANS_NONE and unlock + ** the pager if this call closed the only read or write transaction. + */ + p->inTrans = TRANS_NONE; + unlockBtreeIfUnused(pBt); + + btreeIntegrity(p); + sqlite3BtreeLeave(p); + return SQLITE_OK; +} + +/* +** Do both phases of a commit. +*/ +int sqlite3BtreeCommit(Btree *p){ + int rc; + sqlite3BtreeEnter(p); + rc = sqlite3BtreeCommitPhaseOne(p, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeCommitPhaseTwo(p); + } + sqlite3BtreeLeave(p); + return rc; +} + +#ifndef NDEBUG +/* +** Return the number of write-cursors open on this handle. This is for use +** in assert() expressions, so it is only compiled if NDEBUG is not +** defined. +** +** For the purposes of this routine, a write-cursor is any cursor that +** is capable of writing to the databse. That means the cursor was +** originally opened for writing and the cursor has not be disabled +** by having its state changed to CURSOR_FAULT. +*/ +static int countWriteCursors(BtShared *pBt){ + BtCursor *pCur; + int r = 0; + for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ + if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; + } + return r; +} +#endif + +/* +** This routine sets the state to CURSOR_FAULT and the error +** code to errCode for every cursor on BtShared that pBtree +** references. +** +** Every cursor is tripped, including cursors that belong +** to other database connections that happen to be sharing +** the cache with pBtree. +** +** This routine gets called when a rollback occurs. +** All cursors using the same cache must be tripped +** to prevent them from trying to use the btree after +** the rollback. The rollback may have deleted tables +** or moved root pages, so it is not sufficient to +** save the state of the cursor. The cursor must be +** invalidated. +*/ +void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ + BtCursor *p; + sqlite3BtreeEnter(pBtree); + for(p=pBtree->pBt->pCursor; p; p=p->pNext){ + clearCursorPosition(p); + p->eState = CURSOR_FAULT; + p->skip = errCode; + } + sqlite3BtreeLeave(pBtree); +} + +/* +** Rollback the transaction in progress. All cursors will be +** invalided by this operation. Any attempt to use a cursor +** that was open at the beginning of this operation will result +** in an error. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +int sqlite3BtreeRollback(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + MemPage *pPage1; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + rc = saveAllCursors(pBt, 0, 0); +#ifndef SQLITE_OMIT_SHARED_CACHE + if( rc!=SQLITE_OK ){ + /* This is a horrible situation. An IO or malloc() error occured whilst + ** trying to save cursor positions. If this is an automatic rollback (as + ** the result of a constraint, malloc() failure or IO error) then + ** the cache may be internally inconsistent (not contain valid trees) so + ** we cannot simply return the error to the caller. Instead, abort + ** all queries that may be using any of the cursors that failed to save. + */ + sqlite3BtreeTripAllCursors(p, rc); + } +#endif + btreeIntegrity(p); + unlockAllTables(p); + + if( p->inTrans==TRANS_WRITE ){ + int rc2; + +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->nTrunc = 0; +#endif + + assert( TRANS_WRITE==pBt->inTransaction ); + rc2 = sqlite3PagerRollback(pBt->pPager); + if( rc2!=SQLITE_OK ){ + rc = rc2; + } + + /* The rollback may have destroyed the pPage1->aData value. So + ** call sqlite3BtreeGetPage() on page 1 again to make + ** sure pPage1->aData is set correctly. */ + if( sqlite3BtreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ + releasePage(pPage1); + } + assert( countWriteCursors(pBt)==0 ); + pBt->inTransaction = TRANS_READ; + } + + if( p->inTrans!=TRANS_NONE ){ + assert( pBt->nTransaction>0 ); + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + p->inTrans = TRANS_NONE; + pBt->inStmt = 0; + unlockBtreeIfUnused(pBt); + + btreeIntegrity(p); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Start a statement subtransaction. The subtransaction can +** can be rolled back independently of the main transaction. +** You must start a transaction before starting a subtransaction. +** The subtransaction is ended automatically if the main transaction +** commits or rolls back. +** +** Only one subtransaction may be active at a time. It is an error to try +** to start a new subtransaction if another subtransaction is already active. +** +** Statement subtransactions are used around individual SQL statements +** that are contained within a BEGIN...COMMIT block. If a constraint +** error occurs within the statement, the effect of that one statement +** can be rolled back without having to rollback the entire transaction. +*/ +int sqlite3BtreeBeginStmt(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( (p->inTrans!=TRANS_WRITE) || pBt->inStmt ){ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + }else{ + assert( pBt->inTransaction==TRANS_WRITE ); + rc = pBt->readOnly ? SQLITE_OK : sqlite3PagerStmtBegin(pBt->pPager); + pBt->inStmt = 1; + } + sqlite3BtreeLeave(p); + return rc; +} + + +/* +** Commit the statment subtransaction currently in progress. If no +** subtransaction is active, this is a no-op. +*/ +int sqlite3BtreeCommitStmt(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3PagerStmtCommit(pBt->pPager); + }else{ + rc = SQLITE_OK; + } + pBt->inStmt = 0; + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Rollback the active statement subtransaction. If no subtransaction +** is active this routine is a no-op. +** +** All cursors will be invalidated by this operation. Any attempt +** to use a cursor that was open at the beginning of this operation +** will result in an error. +*/ +int sqlite3BtreeRollbackStmt(Btree *p){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3PagerStmtRollback(pBt->pPager); + assert( countWriteCursors(pBt)==0 ); + pBt->inStmt = 0; + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Default key comparison function to be used if no comparison function +** is specified on the sqlite3BtreeCursor() call. +*/ +static int dfltCompare( + void *NotUsed, /* User data is not used */ + int n1, const void *p1, /* First key to compare */ + int n2, const void *p2 /* Second key to compare */ +){ + int c; + c = memcmp(p1, p2, n1pBt; + + assert( sqlite3BtreeHoldsMutex(p) ); + *ppCur = 0; + if( wrFlag ){ + if( pBt->readOnly ){ + return SQLITE_READONLY; + } + if( checkReadLocks(p, iTable, 0) ){ + return SQLITE_LOCKED; + } + } + + if( pBt->pPage1==0 ){ + rc = lockBtreeWithRetry(p); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pBt->readOnly && wrFlag ){ + return SQLITE_READONLY; + } + } + pCur = sqlite3MallocZero( sizeof(*pCur) ); + if( pCur==0 ){ + rc = SQLITE_NOMEM; + goto create_cursor_exception; + } + pCur->pgnoRoot = (Pgno)iTable; + if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){ + rc = SQLITE_EMPTY; + goto create_cursor_exception; + } + rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); + if( rc!=SQLITE_OK ){ + goto create_cursor_exception; + } + + /* Now that no other errors can occur, finish filling in the BtCursor + ** variables, link the cursor into the BtShared list and set *ppCur (the + ** output argument to this function). + */ + pCur->xCompare = xCmp ? xCmp : dfltCompare; + pCur->pArg = pArg; + pCur->pBtree = p; + pCur->pBt = pBt; + pCur->wrFlag = wrFlag; + pCur->pNext = pBt->pCursor; + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur; + } + pBt->pCursor = pCur; + pCur->eState = CURSOR_INVALID; + *ppCur = pCur; + + return SQLITE_OK; + +create_cursor_exception: + if( pCur ){ + releasePage(pCur->pPage); + sqlite3_free(pCur); + } + unlockBtreeIfUnused(pBt); + return rc; +} +int sqlite3BtreeCursor( + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + int (*xCmp)(void*,int,const void*,int,const void*), /* Key Comparison func */ + void *pArg, /* First arg to xCompare() */ + BtCursor **ppCur /* Write new cursor here */ +){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->db = p->db; + rc = btreeCursor(p, iTable, wrFlag, xCmp, pArg, ppCur); + sqlite3BtreeLeave(p); + return rc; +} + + +/* +** Close a cursor. The read lock on the database file is released +** when the last cursor is closed. +*/ +int sqlite3BtreeCloseCursor(BtCursor *pCur){ + BtShared *pBt = pCur->pBt; + Btree *pBtree = pCur->pBtree; + + sqlite3BtreeEnter(pBtree); + pBt->db = pBtree->db; + clearCursorPosition(pCur); + if( pCur->pPrev ){ + pCur->pPrev->pNext = pCur->pNext; + }else{ + pBt->pCursor = pCur->pNext; + } + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur->pPrev; + } + releasePage(pCur->pPage); + unlockBtreeIfUnused(pBt); + invalidateOverflowCache(pCur); + sqlite3_free(pCur); + sqlite3BtreeLeave(pBtree); + return SQLITE_OK; +} + +/* +** Make a temporary cursor by filling in the fields of pTempCur. +** The temporary cursor is not on the cursor list for the Btree. +*/ +void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ + assert( cursorHoldsMutex(pCur) ); + memcpy(pTempCur, pCur, sizeof(*pCur)); + pTempCur->pNext = 0; + pTempCur->pPrev = 0; + if( pTempCur->pPage ){ + sqlite3PagerRef(pTempCur->pPage->pDbPage); + } +} + +/* +** Delete a temporary cursor such as was made by the CreateTemporaryCursor() +** function above. +*/ +void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + if( pCur->pPage ){ + sqlite3PagerUnref(pCur->pPage->pDbPage); + } +} + +/* +** Make sure the BtCursor* given in the argument has a valid +** BtCursor.info structure. If it is not already valid, call +** sqlite3BtreeParseCell() to fill it in. +** +** BtCursor.info is a cache of the information in the current cell. +** Using this cache reduces the number of calls to sqlite3BtreeParseCell(). +** +** 2007-06-25: There is a bug in some versions of MSVC that cause the +** compiler to crash when getCellInfo() is implemented as a macro. +** But there is a measureable speed advantage to using the macro on gcc +** (when less compiler optimizations like -Os or -O0 are used and the +** compiler is not doing agressive inlining.) So we use a real function +** for MSVC and a macro for everything else. Ticket #2457. +*/ +#ifndef NDEBUG + static void assertCellInfo(BtCursor *pCur){ + CellInfo info; + memset(&info, 0, sizeof(info)); + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &info); + assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); + } +#else + #define assertCellInfo(x) +#endif +#ifdef _MSC_VER + /* Use a real function in MSVC to work around bugs in that compiler. */ + static void getCellInfo(BtCursor *pCur){ + if( pCur->info.nSize==0 ){ + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); + }else{ + assertCellInfo(pCur); + } + } +#else /* if not _MSC_VER */ + /* Use a macro in all other compilers so that the function is inlined */ +#define getCellInfo(pCur) \ + if( pCur->info.nSize==0 ){ \ + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ + }else{ \ + assertCellInfo(pCur); \ + } +#endif /* _MSC_VER */ + +/* +** Set *pSize to the size of the buffer needed to hold the value of +** the key for the current entry. If the cursor is not pointing +** to a valid entry, *pSize is set to 0. +** +** For a table with the INTKEY flag set, this routine returns the key +** itself, not the number of bytes in the key. +*/ +int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nKey; + } + } + return rc; +} + +/* +** Set *pSize to the number of bytes of data in the entry the +** cursor currently points to. Always return SQLITE_OK. +** Failure is not possible. If the cursor is not currently +** pointing to an entry (which can happen, for example, if +** the database is empty) then *pSize is set to 0. +*/ +int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + /* Not pointing at a valid entry - set *pSize to 0. */ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nData; + } + } + return rc; +} + +/* +** Given the page number of an overflow page in the database (parameter +** ovfl), this function finds the page number of the next page in the +** linked list of overflow pages. If possible, it uses the auto-vacuum +** pointer-map data instead of reading the content of page ovfl to do so. +** +** If an error occurs an SQLite error code is returned. Otherwise: +** +** Unless pPgnoNext is NULL, the page number of the next overflow +** page in the linked list is written to *pPgnoNext. If page ovfl +** is the last page in its linked list, *pPgnoNext is set to zero. +** +** If ppPage is not NULL, *ppPage is set to the MemPage* handle +** for page ovfl. The underlying pager page may have been requested +** with the noContent flag set, so the page data accessable via +** this handle may not be trusted. +*/ +static int getOverflowPage( + BtShared *pBt, + Pgno ovfl, /* Overflow page */ + MemPage **ppPage, /* OUT: MemPage handle */ + Pgno *pPgnoNext /* OUT: Next overflow page number */ +){ + Pgno next = 0; + int rc; + + assert( sqlite3_mutex_held(pBt->mutex) ); + /* One of these must not be NULL. Otherwise, why call this function? */ + assert(ppPage || pPgnoNext); + + /* If pPgnoNext is NULL, then this function is being called to obtain + ** a MemPage* reference only. No page-data is required in this case. + */ + if( !pPgnoNext ){ + return sqlite3BtreeGetPage(pBt, ovfl, ppPage, 1); + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* Try to find the next page in the overflow list using the + ** autovacuum pointer-map pages. Guess that the next page in + ** the overflow list is page number (ovfl+1). If that guess turns + ** out to be wrong, fall back to loading the data of page + ** number ovfl to determine the next page number. + */ + if( pBt->autoVacuum ){ + Pgno pgno; + Pgno iGuess = ovfl+1; + u8 eType; + + while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ + iGuess++; + } + + if( iGuess<=sqlite3PagerPagecount(pBt->pPager) ){ + rc = ptrmapGet(pBt, iGuess, &eType, &pgno); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ + next = iGuess; + } + } + } +#endif + + if( next==0 || ppPage ){ + MemPage *pPage = 0; + + rc = sqlite3BtreeGetPage(pBt, ovfl, &pPage, next!=0); + assert(rc==SQLITE_OK || pPage==0); + if( next==0 && rc==SQLITE_OK ){ + next = get4byte(pPage->aData); + } + + if( ppPage ){ + *ppPage = pPage; + }else{ + releasePage(pPage); + } + } + *pPgnoNext = next; + + return rc; +} + +/* +** Copy data from a buffer to a page, or from a page to a buffer. +** +** pPayload is a pointer to data stored on database page pDbPage. +** If argument eOp is false, then nByte bytes of data are copied +** from pPayload to the buffer pointed at by pBuf. If eOp is true, +** then sqlite3PagerWrite() is called on pDbPage and nByte bytes +** of data are copied from the buffer pBuf to pPayload. +** +** SQLITE_OK is returned on success, otherwise an error code. +*/ +static int copyPayload( + void *pPayload, /* Pointer to page data */ + void *pBuf, /* Pointer to buffer */ + int nByte, /* Number of bytes to copy */ + int eOp, /* 0 -> copy from page, 1 -> copy to page */ + DbPage *pDbPage /* Page containing pPayload */ +){ + if( eOp ){ + /* Copy data from buffer to page (a write operation) */ + int rc = sqlite3PagerWrite(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + memcpy(pPayload, pBuf, nByte); + }else{ + /* Copy data from page to buffer (a read operation) */ + memcpy(pBuf, pPayload, nByte); + } + return SQLITE_OK; +} + +/* +** This function is used to read or overwrite payload information +** for the entry that the pCur cursor is pointing to. If the eOp +** parameter is 0, this is a read operation (data copied into +** buffer pBuf). If it is non-zero, a write (data copied from +** buffer pBuf). +** +** A total of "amt" bytes are read or written beginning at "offset". +** Data is read to or from the buffer pBuf. +** +** This routine does not make a distinction between key and data. +** It just reads or writes bytes from the payload area. Data might +** appear on the main page or be scattered out on multiple overflow +** pages. +** +** If the BtCursor.isIncrblobHandle flag is set, and the current +** cursor entry uses one or more overflow pages, this function +** allocates space for and lazily popluates the overflow page-list +** cache array (BtCursor.aOverflow). Subsequent calls use this +** cache to make seeking to the supplied offset more efficient. +** +** Once an overflow page-list cache has been allocated, it may be +** invalidated if some other cursor writes to the same table, or if +** the cursor is moved to a different row. Additionally, in auto-vacuum +** mode, the following events may invalidate an overflow page-list cache. +** +** * An incremental vacuum, +** * A commit in auto_vacuum="full" mode, +** * Creating a table (may require moving an overflow page). +*/ +static int accessPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + int offset, /* Begin reading this far into payload */ + int amt, /* Read this many bytes */ + unsigned char *pBuf, /* Write the bytes into this buffer */ + int skipKey, /* offset begins at data if this is true */ + int eOp /* zero to read. non-zero to write. */ +){ + unsigned char *aPayload; + int rc = SQLITE_OK; + u32 nKey; + int iIdx = 0; + MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ + BtShared *pBt; /* Btree this cursor belongs to */ + + assert( pPage ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->idx>=0 && pCur->idxnCell ); + assert( offset>=0 ); + assert( cursorHoldsMutex(pCur) ); + + getCellInfo(pCur); + aPayload = pCur->info.pCell + pCur->info.nHeader; + nKey = (pPage->intKey ? 0 : pCur->info.nKey); + + if( skipKey ){ + offset += nKey; + } + if( offset+amt > nKey+pCur->info.nData ){ + /* Trying to read or write past the end of the data is an error */ + return SQLITE_ERROR; + } + + /* Check if data must be read/written to/from the btree page itself. */ + if( offsetinfo.nLocal ){ + int a = amt; + if( a+offset>pCur->info.nLocal ){ + a = pCur->info.nLocal - offset; + } + rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); + offset = 0; + pBuf += a; + amt -= a; + }else{ + offset -= pCur->info.nLocal; + } + + pBt = pCur->pBt; + if( rc==SQLITE_OK && amt>0 ){ + const int ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ + Pgno nextPage; + + nextPage = get4byte(&aPayload[pCur->info.nLocal]); + +#ifndef SQLITE_OMIT_INCRBLOB + /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] + ** has not been allocated, allocate it now. The array is sized at + ** one entry for each overflow page in the overflow chain. The + ** page number of the first overflow page is stored in aOverflow[0], + ** etc. A value of 0 in the aOverflow[] array means "not yet known" + ** (the cache is lazily populated). + */ + if( pCur->isIncrblobHandle && !pCur->aOverflow ){ + int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; + pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl); + if( nOvfl && !pCur->aOverflow ){ + rc = SQLITE_NOMEM; + } + } + + /* If the overflow page-list cache has been allocated and the + ** entry for the first required overflow page is valid, skip + ** directly to it. + */ + if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){ + iIdx = (offset/ovflSize); + nextPage = pCur->aOverflow[iIdx]; + offset = (offset%ovflSize); + } +#endif + + for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ + +#ifndef SQLITE_OMIT_INCRBLOB + /* If required, populate the overflow page-list cache. */ + if( pCur->aOverflow ){ + assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); + pCur->aOverflow[iIdx] = nextPage; + } +#endif + + if( offset>=ovflSize ){ + /* The only reason to read this page is to obtain the page + ** number for the next page in the overflow chain. The page + ** data is not required. So first try to lookup the overflow + ** page-list cache, if any, then fall back to the getOverflowPage() + ** function. + */ +#ifndef SQLITE_OMIT_INCRBLOB + if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){ + nextPage = pCur->aOverflow[iIdx+1]; + } else +#endif + rc = getOverflowPage(pBt, nextPage, 0, &nextPage); + offset -= ovflSize; + }else{ + /* Need to read this page properly. It contains some of the + ** range of data that is being read (eOp==0) or written (eOp!=0). + */ + DbPage *pDbPage; + int a = amt; + rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage); + if( rc==SQLITE_OK ){ + aPayload = sqlite3PagerGetData(pDbPage); + nextPage = get4byte(aPayload); + if( a + offset > ovflSize ){ + a = ovflSize - offset; + } + rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); + sqlite3PagerUnref(pDbPage); + offset = 0; + amt -= a; + pBuf += a; + } + } + } + } + + if( rc==SQLITE_OK && amt>0 ){ + return SQLITE_CORRUPT_BKPT; + } + return rc; +} + +/* +** Read part of the key associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + if( pCur->pPage->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pCur->pPage->intKey==0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); + } + return rc; +} + +/* +** Read part of the data associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); + } + return rc; +} + +/* +** Return a pointer to payload information from the entry that the +** pCur cursor is pointing to. The pointer is to the beginning of +** the key if skipKey==0 and it points to the beginning of data if +** skipKey==1. The number of bytes of available key/data is written +** into *pAmt. If *pAmt==0, then the value returned will not be +** a valid pointer. +** +** This routine is an optimization. It is common for the entire key +** and data to fit on the local page and for there to be no overflow +** pages. When that is so, this routine can be used to access the +** key and data without making a copy. If the key and/or data spills +** onto overflow pages, then accessPayload() must be used to reassembly +** the key/data and copy it into a preallocated buffer. +** +** The pointer returned by this routine looks directly into the cached +** page of the database. The data might change or move the next time +** any btree routine is called. +*/ +static const unsigned char *fetchPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + int *pAmt, /* Write the number of available bytes here */ + int skipKey /* read beginning at data if this is true */ +){ + unsigned char *aPayload; + MemPage *pPage; + u32 nKey; + int nLocal; + + assert( pCur!=0 && pCur->pPage!=0 ); + assert( pCur->eState==CURSOR_VALID ); + assert( cursorHoldsMutex(pCur) ); + pPage = pCur->pPage; + assert( pCur->idx>=0 && pCur->idxnCell ); + getCellInfo(pCur); + aPayload = pCur->info.pCell; + aPayload += pCur->info.nHeader; + if( pPage->intKey ){ + nKey = 0; + }else{ + nKey = pCur->info.nKey; + } + if( skipKey ){ + aPayload += nKey; + nLocal = pCur->info.nLocal - nKey; + }else{ + nLocal = pCur->info.nLocal; + if( nLocal>nKey ){ + nLocal = nKey; + } + } + *pAmt = nLocal; + return aPayload; +} + + +/* +** For the entry that cursor pCur is point to, return as +** many bytes of the key or data as are available on the local +** b-tree page. Write the number of available bytes into *pAmt. +** +** The pointer returned is ephemeral. The key/data may move +** or be destroyed on the next call to any Btree routine, +** including calls from other threads against the same cache. +** Hence, a mutex on the BtShared should be held prior to calling +** this routine. +** +** These routines is used to get quick access to key and data +** in the common case where no overflow pages are used. +*/ +const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ + assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 0); + } + return 0; +} +const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ + assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 1); + } + return 0; +} + + +/* +** Move the cursor down to a new child page. The newPgno argument is the +** page number of the child page to move to. +*/ +static int moveToChild(BtCursor *pCur, u32 newPgno){ + int rc; + MemPage *pNewPage; + MemPage *pOldPage; + BtShared *pBt = pCur->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); + if( rc ) return rc; + pNewPage->idxParent = pCur->idx; + pOldPage = pCur->pPage; + pOldPage->idxShift = 0; + releasePage(pOldPage); + pCur->pPage = pNewPage; + pCur->idx = 0; + pCur->info.nSize = 0; + if( pNewPage->nCell<1 ){ + return SQLITE_CORRUPT_BKPT; + } + return SQLITE_OK; +} + +/* +** Return true if the page is the virtual root of its table. +** +** The virtual root page is the root page for most tables. But +** for the table rooted on page 1, sometime the real root page +** is empty except for the right-pointer. In such cases the +** virtual root page is the page that the right-pointer of page +** 1 is pointing to. +*/ +int sqlite3BtreeIsRootPage(MemPage *pPage){ + MemPage *pParent; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pParent = pPage->pParent; + if( pParent==0 ) return 1; + if( pParent->pgno>1 ) return 0; + if( get2byte(&pParent->aData[pParent->hdrOffset+3])==0 ) return 1; + return 0; +} + +/* +** Move the cursor up to the parent page. +** +** pCur->idx is set to the cell index that contains the pointer +** to the page we are coming from. If we are coming from the +** right-most child page then pCur->idx is set to one more than +** the largest cell index. +*/ +void sqlite3BtreeMoveToParent(BtCursor *pCur){ + MemPage *pParent; + MemPage *pPage; + int idxParent; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + pPage = pCur->pPage; + assert( pPage!=0 ); + assert( !sqlite3BtreeIsRootPage(pPage) ); + pParent = pPage->pParent; + assert( pParent!=0 ); + idxParent = pPage->idxParent; + sqlite3PagerRef(pParent->pDbPage); + releasePage(pPage); + pCur->pPage = pParent; + pCur->info.nSize = 0; + assert( pParent->idxShift==0 ); + pCur->idx = idxParent; +} + +/* +** Move the cursor to the root page +*/ +static int moveToRoot(BtCursor *pCur){ + MemPage *pRoot; + int rc = SQLITE_OK; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( CURSOR_INVALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_VALID < CURSOR_REQUIRESEEK ); + assert( CURSOR_FAULT > CURSOR_REQUIRESEEK ); + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + clearCursorPosition(pCur); + } + pRoot = pCur->pPage; + if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ + assert( pRoot->isInit ); + }else{ + if( + SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) + ){ + pCur->eState = CURSOR_INVALID; + return rc; + } + releasePage(pCur->pPage); + pCur->pPage = pRoot; + } + pCur->idx = 0; + pCur->info.nSize = 0; + if( pRoot->nCell==0 && !pRoot->leaf ){ + Pgno subpage; + assert( pRoot->pgno==1 ); + subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); + assert( subpage>0 ); + pCur->eState = CURSOR_VALID; + rc = moveToChild(pCur, subpage); + } + pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID); + return rc; +} + +/* +** Move the cursor down to the left-most leaf entry beneath the +** entry to which it is currently pointing. +** +** The left-most leaf is the one with the smallest key - the first +** in ascending order. +*/ +static int moveToLeftmost(BtCursor *pCur){ + Pgno pgno; + int rc = SQLITE_OK; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + assert( pCur->idx>=0 && pCur->idxnCell ); + pgno = get4byte(findCell(pPage, pCur->idx)); + rc = moveToChild(pCur, pgno); + } + return rc; +} + +/* +** Move the cursor down to the right-most leaf entry beneath the +** page to which it is currently pointing. Notice the difference +** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() +** finds the left-most entry beneath the *entry* whereas moveToRightmost() +** finds the right-most entry beneath the *page*. +** +** The right-most entry is the one with the largest key - the last +** key in ascending order. +*/ +static int moveToRightmost(BtCursor *pCur){ + Pgno pgno; + int rc = SQLITE_OK; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + assert( pCur->eState==CURSOR_VALID ); + while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + pCur->idx = pPage->nCell; + rc = moveToChild(pCur, pgno); + } + if( rc==SQLITE_OK ){ + pCur->idx = pPage->nCell - 1; + pCur->info.nSize = 0; + } + return SQLITE_OK; +} + +/* Move the cursor to the first entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( pCur->eState==CURSOR_INVALID ){ + assert( pCur->pPage->nCell==0 ); + *pRes = 1; + rc = SQLITE_OK; + }else{ + assert( pCur->pPage->nCell>0 ); + *pRes = 0; + rc = moveToLeftmost(pCur); + } + } + return rc; +} + +/* Move the cursor to the last entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc==SQLITE_OK ){ + if( CURSOR_INVALID==pCur->eState ){ + assert( pCur->pPage->nCell==0 ); + *pRes = 1; + }else{ + assert( pCur->eState==CURSOR_VALID ); + *pRes = 0; + rc = moveToRightmost(pCur); + } + } + return rc; +} + +/* Move the cursor so that it points to an entry near pKey/nKey. +** Return a success code. +** +** For INTKEY tables, only the nKey parameter is used. pKey is +** ignored. For other tables, nKey is the number of bytes of data +** in pKey. The comparison function specified when the cursor was +** created is used to compare keys. +** +** If an exact match is not found, then the cursor is always +** left pointing at a leaf page which would hold the entry if it +** were present. The cursor might point to an entry that comes +** before or after the key. +** +** The result of comparing the key with the entry to which the +** cursor is written to *pRes if pRes!=NULL. The meaning of +** this value is as follows: +** +** *pRes<0 The cursor is left pointing at an entry that +** is smaller than pKey or if the table is empty +** and the cursor is therefore left point to nothing. +** +** *pRes==0 The cursor is left pointing at an entry that +** exactly matches pKey. +** +** *pRes>0 The cursor is left pointing at an entry that +** is larger than pKey. +** +*/ +int sqlite3BtreeMoveto( + BtCursor *pCur, /* The cursor to be moved */ + const void *pKey, /* The key content for indices. Not used by tables */ + i64 nKey, /* Size of pKey. Or the key for tables */ + int biasRight, /* If true, bias the search to the high end */ + int *pRes /* Search result flag */ +){ + int rc; + + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + rc = moveToRoot(pCur); + if( rc ){ + return rc; + } + assert( pCur->pPage ); + assert( pCur->pPage->isInit ); + if( pCur->eState==CURSOR_INVALID ){ + *pRes = -1; + assert( pCur->pPage->nCell==0 ); + return SQLITE_OK; + } + for(;;){ + int lwr, upr; + Pgno chldPg; + MemPage *pPage = pCur->pPage; + int c = -1; /* pRes return if table is empty must be -1 */ + lwr = 0; + upr = pPage->nCell-1; + if( !pPage->intKey && pKey==0 ){ + return SQLITE_CORRUPT_BKPT; + } + if( biasRight ){ + pCur->idx = upr; + }else{ + pCur->idx = (upr+lwr)/2; + } + if( lwr<=upr ) for(;;){ + void *pCellKey; + i64 nCellKey; + pCur->info.nSize = 0; + if( pPage->intKey ){ + u8 *pCell; + pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; + if( pPage->hasData ){ + u32 dummy; + pCell += getVarint32(pCell, &dummy); + } + getVarint(pCell, (u64 *)&nCellKey); + if( nCellKeynKey ){ + c = +1; + }else{ + c = 0; + } + }else{ + int available; + pCellKey = (void *)fetchPayload(pCur, &available, 0); + nCellKey = pCur->info.nKey; + if( available>=nCellKey ){ + c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); + }else{ + pCellKey = sqlite3_malloc( nCellKey ); + if( pCellKey==0 ) return SQLITE_NOMEM; + rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); + c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); + sqlite3_free(pCellKey); + if( rc ){ + return rc; + } + } + } + if( c==0 ){ + if( pPage->leafData && !pPage->leaf ){ + lwr = pCur->idx; + upr = lwr - 1; + break; + }else{ + if( pRes ) *pRes = 0; + return SQLITE_OK; + } + } + if( c<0 ){ + lwr = pCur->idx+1; + }else{ + upr = pCur->idx-1; + } + if( lwr>upr ){ + break; + } + pCur->idx = (lwr+upr)/2; + } + assert( lwr==upr+1 ); + assert( pPage->isInit ); + if( pPage->leaf ){ + chldPg = 0; + }else if( lwr>=pPage->nCell ){ + chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); + }else{ + chldPg = get4byte(findCell(pPage, lwr)); + } + if( chldPg==0 ){ + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + if( pRes ) *pRes = c; + return SQLITE_OK; + } + pCur->idx = lwr; + pCur->info.nSize = 0; + rc = moveToChild(pCur, chldPg); + if( rc ){ + return rc; + } + } + /* NOT REACHED */ +} + + +/* +** Return TRUE if the cursor is not pointing at an entry of the table. +** +** TRUE will be returned after a call to sqlite3BtreeNext() moves +** past the last entry in the table or sqlite3BtreePrev() moves past +** the first entry. TRUE is also returned if the table is empty. +*/ +int sqlite3BtreeEof(BtCursor *pCur){ + /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries + ** have been deleted? This API will need to change to return an error code + ** as well as the boolean result value. + */ + return (CURSOR_VALID!=pCur->eState); +} + +/* +** Return the database connection handle for a cursor. +*/ +sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + return pCur->pBtree->db; +} + +/* +** Advance the cursor to the next entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the last entry in the database before +** this routine was called, then set *pRes=1. +*/ +static int btreeNext(BtCursor *pCur, int *pRes){ + int rc; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreOrClearCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pRes!=0 ); + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skip>0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; + + assert( pPage->isInit ); + assert( pCur->idxnCell ); + + pCur->idx++; + pCur->info.nSize = 0; + if( pCur->idx>=pPage->nCell ){ + if( !pPage->leaf ){ + rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); + if( rc ) return rc; + rc = moveToLeftmost(pCur); + *pRes = 0; + return rc; + } + do{ + if( sqlite3BtreeIsRootPage(pPage) ){ + *pRes = 1; + pCur->eState = CURSOR_INVALID; + return SQLITE_OK; + } + sqlite3BtreeMoveToParent(pCur); + pPage = pCur->pPage; + }while( pCur->idx>=pPage->nCell ); + *pRes = 0; + if( pPage->leafData ){ + rc = sqlite3BtreeNext(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + return rc; + } + *pRes = 0; + if( pPage->leaf ){ + return SQLITE_OK; + } + rc = moveToLeftmost(pCur); + return rc; +} +int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ + int rc; + assert( cursorHoldsMutex(pCur) ); + rc = btreeNext(pCur, pRes); + return rc; +} + + +/* +** Step the cursor to the back to the previous entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the first entry in the database before +** this routine was called, then set *pRes=1. +*/ +static int btreePrevious(BtCursor *pCur, int *pRes){ + int rc; + Pgno pgno; + MemPage *pPage; + + assert( cursorHoldsMutex(pCur) ); + rc = restoreOrClearCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skip<0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; + + pPage = pCur->pPage; + assert( pPage->isInit ); + assert( pCur->idx>=0 ); + if( !pPage->leaf ){ + pgno = get4byte( findCell(pPage, pCur->idx) ); + rc = moveToChild(pCur, pgno); + if( rc ){ + return rc; + } + rc = moveToRightmost(pCur); + }else{ + while( pCur->idx==0 ){ + if( sqlite3BtreeIsRootPage(pPage) ){ + pCur->eState = CURSOR_INVALID; + *pRes = 1; + return SQLITE_OK; + } + sqlite3BtreeMoveToParent(pCur); + pPage = pCur->pPage; + } + pCur->idx--; + pCur->info.nSize = 0; + if( pPage->leafData && !pPage->leaf ){ + rc = sqlite3BtreePrevious(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + } + *pRes = 0; + return rc; +} +int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ + int rc; + assert( cursorHoldsMutex(pCur) ); + rc = btreePrevious(pCur, pRes); + return rc; +} + +/* +** Allocate a new page from the database file. +** +** The new page is marked as dirty. (In other words, sqlite3PagerWrite() +** has already been called on the new page.) The new page has also +** been referenced and the calling routine is responsible for calling +** sqlite3PagerUnref() on the new page when it is done. +** +** SQLITE_OK is returned on success. Any other return value indicates +** an error. *ppPage and *pPgno are undefined in the event of an error. +** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. +** +** If the "nearby" parameter is not 0, then a (feeble) effort is made to +** locate a page close to the page number "nearby". This can be used in an +** attempt to keep related pages close to each other in the database file, +** which in turn can make database access faster. +** +** If the "exact" parameter is not 0, and the page-number nearby exists +** anywhere on the free-list, then it is guarenteed to be returned. This +** is only used by auto-vacuum databases when allocating a new table. +*/ +static int allocateBtreePage( + BtShared *pBt, + MemPage **ppPage, + Pgno *pPgno, + Pgno nearby, + u8 exact +){ + MemPage *pPage1; + int rc; + int n; /* Number of pages on the freelist */ + int k; /* Number of leaves on the trunk of the freelist */ + MemPage *pTrunk = 0; + MemPage *pPrevTrunk = 0; + + assert( sqlite3_mutex_held(pBt->mutex) ); + pPage1 = pBt->pPage1; + n = get4byte(&pPage1->aData[36]); + if( n>0 ){ + /* There are pages on the freelist. Reuse one of those pages. */ + Pgno iTrunk; + u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ + + /* If the 'exact' parameter was true and a query of the pointer-map + ** shows that the page 'nearby' is somewhere on the free-list, then + ** the entire-list will be searched for that page. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( exact && nearby<=sqlite3PagerPagecount(pBt->pPager) ){ + u8 eType; + assert( nearby>0 ); + assert( pBt->autoVacuum ); + rc = ptrmapGet(pBt, nearby, &eType, 0); + if( rc ) return rc; + if( eType==PTRMAP_FREEPAGE ){ + searchList = 1; + } + *pPgno = nearby; + } +#endif + + /* Decrement the free-list count by 1. Set iTrunk to the index of the + ** first free-list trunk page. iPrevTrunk is initially 1. + */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + put4byte(&pPage1->aData[36], n-1); + + /* The code within this loop is run only once if the 'searchList' variable + ** is not true. Otherwise, it runs once for each trunk-page on the + ** free-list until the page 'nearby' is located. + */ + do { + pPrevTrunk = pTrunk; + if( pPrevTrunk ){ + iTrunk = get4byte(&pPrevTrunk->aData[0]); + }else{ + iTrunk = get4byte(&pPage1->aData[32]); + } + rc = sqlite3BtreeGetPage(pBt, iTrunk, &pTrunk, 0); + if( rc ){ + pTrunk = 0; + goto end_allocate_page; + } + + k = get4byte(&pTrunk->aData[4]); + if( k==0 && !searchList ){ + /* The trunk has no leaves and the list is not being searched. + ** So extract the trunk page itself and use it as the newly + ** allocated page */ + assert( pPrevTrunk==0 ); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + *pPgno = iTrunk; + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + *ppPage = pTrunk; + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); + }else if( k>pBt->usableSize/4 - 8 ){ + /* Value of k is out of range. Database corruption */ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; +#ifndef SQLITE_OMIT_AUTOVACUUM + }else if( searchList && nearby==iTrunk ){ + /* The list is being searched and this trunk page is the page + ** to allocate, regardless of whether it has leaves. + */ + assert( *pPgno==iTrunk ); + *ppPage = pTrunk; + searchList = 0; + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + if( k==0 ){ + if( !pPrevTrunk ){ + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + }else{ + memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); + } + }else{ + /* The trunk page is required by the caller but it contains + ** pointers to free-list leaves. The first leaf becomes a trunk + ** page in this case. + */ + MemPage *pNewTrunk; + Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); + rc = sqlite3BtreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); + if( rc!=SQLITE_OK ){ + goto end_allocate_page; + } + rc = sqlite3PagerWrite(pNewTrunk->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pNewTrunk); + goto end_allocate_page; + } + memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4); + put4byte(&pNewTrunk->aData[4], k-1); + memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4); + releasePage(pNewTrunk); + if( !pPrevTrunk ){ + put4byte(&pPage1->aData[32], iNewTrunk); + }else{ + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + put4byte(&pPrevTrunk->aData[0], iNewTrunk); + } + } + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); +#endif + }else{ + /* Extract a leaf from the trunk */ + int closest; + Pgno iPage; + unsigned char *aData = pTrunk->aData; + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + if( nearby>0 ){ + int i, dist; + closest = 0; + dist = get4byte(&aData[8]) - nearby; + if( dist<0 ) dist = -dist; + for(i=1; isqlite3PagerPagecount(pBt->pPager) ){ + /* Free page off the end of the file */ + return SQLITE_CORRUPT_BKPT; + } + TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" + ": %d more free pages\n", + *pPgno, closest+1, k, pTrunk->pgno, n-1)); + if( closestpDbPage); + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + } + searchList = 0; + } + } + releasePage(pPrevTrunk); + pPrevTrunk = 0; + }while( searchList ); + }else{ + /* There are no pages on the freelist, so create a new page at the + ** end of the file */ + *pPgno = sqlite3PagerPagecount(pBt->pPager) + 1; + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->nTrunc ){ + /* An incr-vacuum has already run within this transaction. So the + ** page to allocate is not from the physical end of the file, but + ** at pBt->nTrunc. + */ + *pPgno = pBt->nTrunc+1; + if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ + (*pPgno)++; + } + } + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ + /* If *pPgno refers to a pointer-map page, allocate two new pages + ** at the end of the file instead of one. The first allocated page + ** becomes a new pointer-map page, the second is used by the caller. + */ + TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno)); + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + (*pPgno)++; + if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ (*pPgno)++; } + } + if( pBt->nTrunc ){ + pBt->nTrunc = *pPgno; + } +#endif + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 0); + if( rc ) return rc; + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); + } + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + +end_allocate_page: + releasePage(pTrunk); + releasePage(pPrevTrunk); + return rc; +} + +/* +** Add a page of the database file to the freelist. +** +** sqlite3PagerUnref() is NOT called for pPage. +*/ +static int freePage(MemPage *pPage){ + BtShared *pBt = pPage->pBt; + MemPage *pPage1 = pBt->pPage1; + int rc, n, k; + + /* Prepare the page for freeing */ + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + assert( pPage->pgno>1 ); + pPage->isInit = 0; + releasePage(pPage->pParent); + pPage->pParent = 0; + + /* Increment the free page count on pPage1 */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + n = get4byte(&pPage1->aData[36]); + put4byte(&pPage1->aData[36], n+1); + +#ifdef SQLITE_SECURE_DELETE + /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then + ** always fully overwrite deleted information with zeros. + */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memset(pPage->aData, 0, pPage->pBt->pageSize); +#endif + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the database supports auto-vacuum, write an entry in the pointer-map + ** to indicate that the page is free. + */ + if( pBt->autoVacuum ){ + rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0); + if( rc ) return rc; + } +#endif + + if( n==0 ){ + /* This is the first free page */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memset(pPage->aData, 0, 8); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d first\n", pPage->pgno)); + }else{ + /* Other free pages already exist. Retrive the first trunk page + ** of the freelist and find out how many leaves it has. */ + MemPage *pTrunk; + rc = sqlite3BtreeGetPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0); + if( rc ) return rc; + k = get4byte(&pTrunk->aData[4]); + if( k>=pBt->usableSize/4 - 8 ){ + /* The trunk is full. Turn the page being freed into a new + ** trunk page with no leaves. */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(pPage->aData, pTrunk->pgno); + put4byte(&pPage->aData[4], 0); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", + pPage->pgno, pTrunk->pgno)); + } + }else if( k<0 ){ + rc = SQLITE_CORRUPT; + }else{ + /* Add the newly freed page as a leaf on the current trunk */ + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pTrunk->aData[4], k+1); + put4byte(&pTrunk->aData[8+k*4], pPage->pgno); +#ifndef SQLITE_SECURE_DELETE + sqlite3PagerDontWrite(pPage->pDbPage); +#endif + } + TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); + } + releasePage(pTrunk); + } + return rc; +} + +/* +** Free any overflow pages associated with the given Cell. +*/ +static int clearCell(MemPage *pPage, unsigned char *pCell){ + BtShared *pBt = pPage->pBt; + CellInfo info; + Pgno ovflPgno; + int rc; + int nOvfl; + int ovflPageSize; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + if( info.iOverflow==0 ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } + ovflPgno = get4byte(&pCell[info.iOverflow]); + ovflPageSize = pBt->usableSize - 4; + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + assert( ovflPgno==0 || nOvfl>0 ); + while( nOvfl-- ){ + MemPage *pOvfl; + if( ovflPgno==0 || ovflPgno>sqlite3PagerPagecount(pBt->pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno); + if( rc ) return rc; + rc = freePage(pOvfl); + sqlite3PagerUnref(pOvfl->pDbPage); + if( rc ) return rc; + } + return SQLITE_OK; +} + +/* +** Create the byte sequence used to represent a cell on page pPage +** and write that byte sequence into pCell[]. Overflow pages are +** allocated and filled in as necessary. The calling procedure +** is responsible for making sure sufficient space has been allocated +** for pCell[]. +** +** Note that pCell does not necessary need to point to the pPage->aData +** area. pCell might point to some temporary storage. The cell will +** be constructed in this temporary area then copied into pPage->aData +** later. +*/ +static int fillInCell( + MemPage *pPage, /* The page that contains the cell */ + unsigned char *pCell, /* Complete text of the cell */ + const void *pKey, i64 nKey, /* The key */ + const void *pData,int nData, /* The data */ + int nZero, /* Extra zero bytes to append to pData */ + int *pnSize /* Write cell size here */ +){ + int nPayload; + const u8 *pSrc; + int nSrc, n, rc; + int spaceLeft; + MemPage *pOvfl = 0; + MemPage *pToRelease = 0; + unsigned char *pPrior; + unsigned char *pPayload; + BtShared *pBt = pPage->pBt; + Pgno pgnoOvfl = 0; + int nHeader; + CellInfo info; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* Fill in the header. */ + nHeader = 0; + if( !pPage->leaf ){ + nHeader += 4; + } + if( pPage->hasData ){ + nHeader += putVarint(&pCell[nHeader], nData+nZero); + }else{ + nData = nZero = 0; + } + nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( info.nHeader==nHeader ); + assert( info.nKey==nKey ); + assert( info.nData==nData+nZero ); + + /* Fill in the payload */ + nPayload = nData + nZero; + if( pPage->intKey ){ + pSrc = pData; + nSrc = nData; + nData = 0; + }else{ + nPayload += nKey; + pSrc = pKey; + nSrc = nKey; + } + *pnSize = info.nSize; + spaceLeft = info.nLocal; + pPayload = &pCell[nHeader]; + pPrior = &pCell[info.iOverflow]; + + while( nPayload>0 ){ + if( spaceLeft==0 ){ + int isExact = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ + if( pBt->autoVacuum ){ + do{ + pgnoOvfl++; + } while( + PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) + ); + if( pgnoOvfl>1 ){ + /* isExact = 1; */ + } + } +#endif + rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, isExact); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the database supports auto-vacuum, and the second or subsequent + ** overflow page is being allocated, add an entry to the pointer-map + ** for that page now. + ** + ** If this is the first overflow page, then write a partial entry + ** to the pointer-map. If we write nothing to this pointer-map slot, + ** then the optimistic overflow chain processing in clearCell() + ** may misinterpret the uninitialised values and delete the + ** wrong pages from the database. + */ + if( pBt->autoVacuum && rc==SQLITE_OK ){ + u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); + rc = ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap); + if( rc ){ + releasePage(pOvfl); + } + } +#endif + if( rc ){ + releasePage(pToRelease); + return rc; + } + put4byte(pPrior, pgnoOvfl); + releasePage(pToRelease); + pToRelease = pOvfl; + pPrior = pOvfl->aData; + put4byte(pPrior, 0); + pPayload = &pOvfl->aData[4]; + spaceLeft = pBt->usableSize - 4; + } + n = nPayload; + if( n>spaceLeft ) n = spaceLeft; + if( nSrc>0 ){ + if( n>nSrc ) n = nSrc; + assert( pSrc ); + memcpy(pPayload, pSrc, n); + }else{ + memset(pPayload, 0, n); + } + nPayload -= n; + pPayload += n; + pSrc += n; + nSrc -= n; + spaceLeft -= n; + if( nSrc==0 ){ + nSrc = nData; + pSrc = pData; + } + } + releasePage(pToRelease); + return SQLITE_OK; +} + +/* +** Change the MemPage.pParent pointer on the page whose number is +** given in the second argument so that MemPage.pParent holds the +** pointer in the third argument. +*/ +static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ + MemPage *pThis; + DbPage *pDbPage; + + assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pNewParent!=0 ); + if( pgno==0 ) return SQLITE_OK; + assert( pBt->pPager!=0 ); + pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); + if( pDbPage ){ + pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage); + if( pThis->isInit ){ + assert( pThis->aData==sqlite3PagerGetData(pDbPage) ); + if( pThis->pParent!=pNewParent ){ + if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage); + pThis->pParent = pNewParent; + sqlite3PagerRef(pNewParent->pDbPage); + } + pThis->idxParent = idx; + } + sqlite3PagerUnref(pDbPage); + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno); + } +#endif + return SQLITE_OK; +} + + + +/* +** Change the pParent pointer of all children of pPage to point back +** to pPage. +** +** In other words, for every child of pPage, invoke reparentPage() +** to make sure that each child knows that pPage is its parent. +** +** This routine gets called after you memcpy() one page into +** another. +*/ +static int reparentChildPages(MemPage *pPage){ + int i; + BtShared *pBt = pPage->pBt; + int rc = SQLITE_OK; + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->leaf ) return SQLITE_OK; + + for(i=0; inCell; i++){ + u8 *pCell = findCell(pPage, i); + if( !pPage->leaf ){ + rc = reparentPage(pBt, get4byte(pCell), pPage, i); + if( rc!=SQLITE_OK ) return rc; + } + } + if( !pPage->leaf ){ + rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), + pPage, i); + pPage->idxShift = 0; + } + return rc; +} + +/* +** Remove the i-th cell from pPage. This routine effects pPage only. +** The cell content is not freed or deallocated. It is assumed that +** the cell content has been copied someplace else. This routine just +** removes the reference to the cell from pPage. +** +** "sz" must be the number of bytes in the cell. +*/ +static void dropCell(MemPage *pPage, int idx, int sz){ + int i; /* Loop counter */ + int pc; /* Offset to cell content of cell being deleted */ + u8 *data; /* pPage->aData */ + u8 *ptr; /* Used to move bytes around within data[] */ + + assert( idx>=0 && idxnCell ); + assert( sz==cellSize(pPage, idx) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + data = pPage->aData; + ptr = &data[pPage->cellOffset + 2*idx]; + pc = get2byte(ptr); + assert( pc>10 && pc+sz<=pPage->pBt->usableSize ); + freeSpace(pPage, pc, sz); + for(i=idx+1; inCell; i++, ptr+=2){ + ptr[0] = ptr[2]; + ptr[1] = ptr[3]; + } + pPage->nCell--; + put2byte(&data[pPage->hdrOffset+3], pPage->nCell); + pPage->nFree += 2; + pPage->idxShift = 1; +} + +/* +** Insert a new cell on pPage at cell index "i". pCell points to the +** content of the cell. +** +** If the cell content will fit on the page, then put it there. If it +** will not fit, then make a copy of the cell content into pTemp if +** pTemp is not null. Regardless of pTemp, allocate a new entry +** in pPage->aOvfl[] and make it point to the cell content (either +** in pTemp or the original pCell) and also record its index. +** Allocating a new entry in pPage->aCell[] implies that +** pPage->nOverflow is incremented. +** +** If nSkip is non-zero, then do not copy the first nSkip bytes of the +** cell. The caller will overwrite them after this function returns. If +** nSkip is non-zero, then pCell may not point to an invalid memory location +** (but pCell+nSkip is always valid). +*/ +static int insertCell( + MemPage *pPage, /* Page into which we are copying */ + int i, /* New cell becomes the i-th cell of the page */ + u8 *pCell, /* Content of the new cell */ + int sz, /* Bytes of content in pCell */ + u8 *pTemp, /* Temp storage space for pCell, if needed */ + u8 nSkip /* Do not write the first nSkip bytes of the cell */ +){ + int idx; /* Where to write new cell content in data[] */ + int j; /* Loop counter */ + int top; /* First byte of content for any cell in data[] */ + int end; /* First byte past the last cell pointer in data[] */ + int ins; /* Index in data[] where new cell pointer is inserted */ + int hdr; /* Offset into data[] of the page header */ + int cellOffset; /* Address of first cell pointer in data[] */ + u8 *data; /* The content of the whole page */ + u8 *ptr; /* Used for moving information around in data[] */ + + assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); + assert( sz==cellSizePtr(pPage, pCell) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->nOverflow || sz+2>pPage->nFree ){ + if( pTemp ){ + memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); + pCell = pTemp; + } + j = pPage->nOverflow++; + assert( jaOvfl)/sizeof(pPage->aOvfl[0]) ); + pPage->aOvfl[j].pCell = pCell; + pPage->aOvfl[j].idx = i; + pPage->nFree = 0; + }else{ + int rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + data = pPage->aData; + hdr = pPage->hdrOffset; + top = get2byte(&data[hdr+5]); + cellOffset = pPage->cellOffset; + end = cellOffset + 2*pPage->nCell + 2; + ins = cellOffset + 2*i; + if( end > top - sz ){ + rc = defragmentPage(pPage); + if( rc!=SQLITE_OK ) return rc; + top = get2byte(&data[hdr+5]); + assert( end + sz <= top ); + } + idx = allocateSpace(pPage, sz); + assert( idx>0 ); + assert( end <= get2byte(&data[hdr+5]) ); + pPage->nCell++; + pPage->nFree -= 2; + memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); + for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){ + ptr[0] = ptr[-2]; + ptr[1] = ptr[-1]; + } + put2byte(&data[ins], idx); + put2byte(&data[hdr+3], pPage->nCell); + pPage->idxShift = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pPage->pBt->autoVacuum ){ + /* The cell may contain a pointer to an overflow page. If so, write + ** the entry for the overflow page into the pointer map. + */ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); + if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); + rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno); + if( rc!=SQLITE_OK ) return rc; + } + } +#endif + } + + return SQLITE_OK; +} + +/* +** Add a list of cells to a page. The page should be initially empty. +** The cells are guaranteed to fit on the page. +*/ +static void assemblePage( + MemPage *pPage, /* The page to be assemblied */ + int nCell, /* The number of cells to add to this page */ + u8 **apCell, /* Pointers to cell bodies */ + int *aSize /* Sizes of the cells */ +){ + int i; /* Loop counter */ + int totalSize; /* Total size of all cells */ + int hdr; /* Index of page header */ + int cellptr; /* Address of next cell pointer */ + int cellbody; /* Address of next cell body */ + u8 *data; /* Data for the page */ + + assert( pPage->nOverflow==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + totalSize = 0; + for(i=0; inFree ); + assert( pPage->nCell==0 ); + cellptr = pPage->cellOffset; + data = pPage->aData; + hdr = pPage->hdrOffset; + put2byte(&data[hdr+3], nCell); + if( nCell ){ + cellbody = allocateSpace(pPage, totalSize); + assert( cellbody>0 ); + assert( pPage->nFree >= 2*nCell ); + pPage->nFree -= 2*nCell; + for(i=0; ipBt->usableSize ); + } + pPage->nCell = nCell; +} + +/* +** The following parameters determine how many adjacent pages get involved +** in a balancing operation. NN is the number of neighbors on either side +** of the page that participate in the balancing operation. NB is the +** total number of pages that participate, including the target page and +** NN neighbors on either side. +** +** The minimum value of NN is 1 (of course). Increasing NN above 1 +** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance +** in exchange for a larger degradation in INSERT and UPDATE performance. +** The value of NN appears to give the best results overall. +*/ +#define NN 1 /* Number of neighbors on either side of pPage */ +#define NB (NN*2+1) /* Total pages involved in the balance */ + +/* Forward reference */ +static int balance(MemPage*, int); + +#ifndef SQLITE_OMIT_QUICKBALANCE +/* +** This version of balance() handles the common special case where +** a new entry is being inserted on the extreme right-end of the +** tree, in other words, when the new entry will become the largest +** entry in the tree. +** +** Instead of trying balance the 3 right-most leaf pages, just add +** a new page to the right-hand side and put the one new entry in +** that page. This leaves the right side of the tree somewhat +** unbalanced. But odds are that we will be inserting new entries +** at the end soon afterwards so the nearly empty page will quickly +** fill up. On average. +** +** pPage is the leaf page which is the right-most page in the tree. +** pParent is its parent. pPage must have a single overflow entry +** which is also the right-most entry on the page. +*/ +static int balance_quick(MemPage *pPage, MemPage *pParent){ + int rc; + MemPage *pNew; + Pgno pgnoNew; + u8 *pCell; + int szCell; + CellInfo info; + BtShared *pBt = pPage->pBt; + int parentIdx = pParent->nCell; /* pParent new divider cell index */ + int parentSize; /* Size of new divider cell */ + u8 parentCell[64]; /* Space for the new divider cell */ + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* Allocate a new page. Insert the overflow cell from pPage + ** into it. Then remove the overflow cell from pPage. + */ + rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + pCell = pPage->aOvfl[0].pCell; + szCell = cellSizePtr(pPage, pCell); + zeroPage(pNew, pPage->aData[0]); + assemblePage(pNew, 1, &pCell, &szCell); + pPage->nOverflow = 0; + + /* Set the parent of the newly allocated page to pParent. */ + pNew->pParent = pParent; + sqlite3PagerRef(pParent->pDbPage); + + /* pPage is currently the right-child of pParent. Change this + ** so that the right-child is the new page allocated above and + ** pPage is the next-to-right child. + */ + assert( pPage->nCell>0 ); + pCell = findCell(pPage, pPage->nCell-1); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( parentSize<64 ); + rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); + if( rc!=SQLITE_OK ){ + return rc; + } + put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno); + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If this is an auto-vacuum database, update the pointer map + ** with entries for the new page, and any pointer from the + ** cell on the page to an overflow page. + */ + if( pBt->autoVacuum ){ + rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno); + if( rc==SQLITE_OK ){ + rc = ptrmapPutOvfl(pNew, 0); + } + if( rc!=SQLITE_OK ){ + releasePage(pNew); + return rc; + } + } +#endif + + /* Release the reference to the new page and balance the parent page, + ** in case the divider cell inserted caused it to become overfull. + */ + releasePage(pNew); + return balance(pParent, 0); +} +#endif /* SQLITE_OMIT_QUICKBALANCE */ + +/* +** This routine redistributes Cells on pPage and up to NN*2 siblings +** of pPage so that all pages have about the same amount of free space. +** Usually NN siblings on either side of pPage is used in the balancing, +** though more siblings might come from one side if pPage is the first +** or last child of its parent. If pPage has fewer than 2*NN siblings +** (something which can only happen if pPage is the root page or a +** child of root) then all available siblings participate in the balancing. +** +** The number of siblings of pPage might be increased or decreased by one or +** two in an effort to keep pages nearly full but not over full. The root page +** is special and is allowed to be nearly empty. If pPage is +** the root page, then the depth of the tree might be increased +** or decreased by one, as necessary, to keep the root page from being +** overfull or completely empty. +** +** Note that when this routine is called, some of the Cells on pPage +** might not actually be stored in pPage->aData[]. This can happen +** if the page is overfull. Part of the job of this routine is to +** make sure all Cells for pPage once again fit in pPage->aData[]. +** +** In the course of balancing the siblings of pPage, the parent of pPage +** might become overfull or underfull. If that happens, then this routine +** is called recursively on the parent. +** +** If this routine fails for any reason, it might leave the database +** in a corrupted state. So if this routine fails, the database should +** be rolled back. +*/ +static int balance_nonroot(MemPage *pPage){ + MemPage *pParent; /* The parent of pPage */ + BtShared *pBt; /* The whole database */ + int nCell = 0; /* Number of cells in apCell[] */ + int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ + int nOld; /* Number of pages in apOld[] */ + int nNew; /* Number of pages in apNew[] */ + int nDiv; /* Number of cells in apDiv[] */ + int i, j, k; /* Loop counters */ + int idx; /* Index of pPage in pParent->aCell[] */ + int nxDiv; /* Next divider slot in pParent->aCell[] */ + int rc; /* The return code */ + int leafCorrection; /* 4 if pPage is a leaf. 0 if not */ + int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ + int usableSpace; /* Bytes in pPage beyond the header */ + int pageFlags; /* Value of pPage->aData[0] */ + int subtotal; /* Subtotal of bytes in cells on one page */ + int iSpace = 0; /* First unused byte of aSpace[] */ + MemPage *apOld[NB]; /* pPage and up to two siblings */ + Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ + MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ + MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ + Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */ + u8 *apDiv[NB]; /* Divider cells in pParent */ + int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ + int szNew[NB+2]; /* Combined size of cells place on i-th page */ + u8 **apCell = 0; /* All cells begin balanced */ + int *szCell; /* Local size of all cells in apCell[] */ + u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ + u8 *aSpace; /* Space to hold copies of dividers cells */ +#ifndef SQLITE_OMIT_AUTOVACUUM + u8 *aFrom = 0; +#endif + + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + + /* + ** Find the parent page. + */ + assert( pPage->isInit ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 ); + pBt = pPage->pBt; + pParent = pPage->pParent; + assert( pParent ); + if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){ + return rc; + } + TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); + +#ifndef SQLITE_OMIT_QUICKBALANCE + /* + ** A special case: If a new entry has just been inserted into a + ** table (that is, a btree with integer keys and all data at the leaves) + ** and the new entry is the right-most entry in the tree (it has the + ** largest key) then use the special balance_quick() routine for + ** balancing. balance_quick() is much faster and results in a tighter + ** packing of data in the common case. + */ + if( pPage->leaf && + pPage->intKey && + pPage->leafData && + pPage->nOverflow==1 && + pPage->aOvfl[0].idx==pPage->nCell && + pPage->pParent->pgno!=1 && + get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno + ){ + /* + ** TODO: Check the siblings to the left of pPage. It may be that + ** they are not full and no new page is required. + */ + return balance_quick(pPage, pParent); + } +#endif + + if( SQLITE_OK!=(rc = sqlite3PagerWrite(pPage->pDbPage)) ){ + return rc; + } + + /* + ** Find the cell in the parent page whose left child points back + ** to pPage. The "idx" variable is the index of that cell. If pPage + ** is the rightmost child of pParent then set idx to pParent->nCell + */ + if( pParent->idxShift ){ + Pgno pgno; + pgno = pPage->pgno; + assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + for(idx=0; idxnCell; idx++){ + if( get4byte(findCell(pParent, idx))==pgno ){ + break; + } + } + assert( idxnCell + || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno ); + }else{ + idx = pPage->idxParent; + } + + /* + ** Initialize variables so that it will be safe to jump + ** directly to balance_cleanup at any moment. + */ + nOld = nNew = 0; + sqlite3PagerRef(pParent->pDbPage); + + /* + ** Find sibling pages to pPage and the cells in pParent that divide + ** the siblings. An attempt is made to find NN siblings on either + ** side of pPage. More siblings are taken from one side, however, if + ** pPage there are fewer than NN siblings on the other side. If pParent + ** has NB or fewer children then all children of pParent are taken. + */ + nxDiv = idx - NN; + if( nxDiv + NB > pParent->nCell ){ + nxDiv = pParent->nCell - NB + 1; + } + if( nxDiv<0 ){ + nxDiv = 0; + } + nDiv = 0; + for(i=0, k=nxDiv; inCell ){ + apDiv[i] = findCell(pParent, k); + nDiv++; + assert( !pParent->leaf ); + pgnoOld[i] = get4byte(apDiv[i]); + }else if( k==pParent->nCell ){ + pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); + }else{ + break; + } + rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent); + if( rc ) goto balance_cleanup; + apOld[i]->idxParent = k; + apCopy[i] = 0; + assert( i==nOld ); + nOld++; + nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; + } + + /* Make nMaxCells a multiple of 2 in order to preserve 8-byte + ** alignment */ + nMaxCells = (nMaxCells + 1)&~1; + + /* + ** Allocate space for memory structures + */ + apCell = sqlite3_malloc( + nMaxCells*sizeof(u8*) /* apCell */ + + nMaxCells*sizeof(int) /* szCell */ + + ROUND8(sizeof(MemPage))*NB /* aCopy */ + + pBt->pageSize*(5+NB) /* aSpace */ + + (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */ + ); + if( apCell==0 ){ + rc = SQLITE_NOMEM; + goto balance_cleanup; + } + szCell = (int*)&apCell[nMaxCells]; + aCopy[0] = (u8*)&szCell[nMaxCells]; + assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + for(i=1; ipageSize+ROUND8(sizeof(MemPage))]; + assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + } + aSpace = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))]; + assert( ((aSpace - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + aFrom = &aSpace[5*pBt->pageSize]; + } +#endif + + /* + ** Make copies of the content of pPage and its siblings into aOld[]. + ** The rest of this function will use data from the copies rather + ** that the original pages since the original pages will be in the + ** process of being overwritten. + */ + for(i=0; iaData = (void*)&p[1]; + memcpy(p->aData, apOld[i]->aData, pBt->pageSize); + } + + /* + ** Load pointers to all cells on sibling pages and the divider cells + ** into the local apCell[] array. Make copies of the divider cells + ** into space obtained form aSpace[] and remove the the divider Cells + ** from pParent. + ** + ** If the siblings are on leaf pages, then the child pointers of the + ** divider cells are stripped from the cells before they are copied + ** into aSpace[]. In this way, all cells in apCell[] are without + ** child pointers. If siblings are not leaves, then all cell in + ** apCell[] include child pointers. Either way, all cells in apCell[] + ** are alike. + ** + ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. + ** leafData: 1 if pPage holds key+data and pParent holds only keys. + */ + nCell = 0; + leafCorrection = pPage->leaf*4; + leafData = pPage->leafData && pPage->leaf; + for(i=0; inCell+pOld->nOverflow; + for(j=0; jautoVacuum ){ + int a; + aFrom[nCell] = i; + for(a=0; anOverflow; a++){ + if( pOld->aOvfl[a].pCell==apCell[nCell] ){ + aFrom[nCell] = 0xFF; + break; + } + } + } +#endif + nCell++; + } + if( ipageSize*5 ); + memcpy(pTemp, apDiv[i], sz); + apCell[nCell] = pTemp+leafCorrection; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + aFrom[nCell] = 0xFF; + } +#endif + dropCell(pParent, nxDiv, sz); + szCell[nCell] -= leafCorrection; + assert( get4byte(pTemp)==pgnoOld[i] ); + if( !pOld->leaf ){ + assert( leafCorrection==0 ); + /* The right pointer of the child page pOld becomes the left + ** pointer of the divider cell */ + memcpy(apCell[nCell], &pOld->aData[pOld->hdrOffset+8], 4); + }else{ + assert( leafCorrection==4 ); + if( szCell[nCell]<4 ){ + /* Do not allow any cells smaller than 4 bytes. */ + szCell[nCell] = 4; + } + } + nCell++; + } + } + } + + /* + ** Figure out the number of pages needed to hold all nCell cells. + ** Store this number in "k". Also compute szNew[] which is the total + ** size of all cells on the i-th page and cntNew[] which is the index + ** in apCell[] of the cell that divides page i from page i+1. + ** cntNew[k] should equal nCell. + ** + ** Values computed by this block: + ** + ** k: The total number of sibling pages + ** szNew[i]: Spaced used on the i-th sibling page. + ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to + ** the right of the i-th sibling page. + ** usableSpace: Number of bytes of space available on each sibling. + ** + */ + usableSpace = pBt->usableSize - 12 + leafCorrection; + for(subtotal=k=i=0; i usableSpace ){ + szNew[k] = subtotal - szCell[i]; + cntNew[k] = i; + if( leafData ){ i--; } + subtotal = 0; + k++; + } + } + szNew[k] = subtotal; + cntNew[k] = nCell; + k++; + + /* + ** The packing computed by the previous block is biased toward the siblings + ** on the left side. The left siblings are always nearly full, while the + ** right-most sibling might be nearly empty. This block of code attempts + ** to adjust the packing of siblings to get a better balance. + ** + ** This adjustment is more than an optimization. The packing above might + ** be so out of balance as to be illegal. For example, the right-most + ** sibling might be completely empty. This adjustment is not optional. + */ + for(i=k-1; i>0; i--){ + int szRight = szNew[i]; /* Size of sibling on the right */ + int szLeft = szNew[i-1]; /* Size of sibling on the left */ + int r; /* Index of right-most cell in left sibling */ + int d; /* Index of first cell to the left of right sibling */ + + r = cntNew[i-1] - 1; + d = r + 1 - leafData; + assert( d0) or we are the + ** a virtual root page. A virtual root page is when the real root + ** page is page 1 and we are the only child of that page. + */ + assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) ); + + /* + ** Allocate k new pages. Reuse old pages where possible. + */ + assert( pPage->pgno>1 ); + pageFlags = pPage->aData[0]; + for(i=0; ipDbPage); + nNew++; + if( rc ) goto balance_cleanup; + }else{ + assert( i>0 ); + rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); + if( rc ) goto balance_cleanup; + apNew[i] = pNew; + nNew++; + } + zeroPage(pNew, pageFlags); + } + + /* Free any old pages that were not reused as new pages. + */ + while( ii ){ + int t; + MemPage *pT; + t = pgnoNew[i]; + pT = apNew[i]; + pgnoNew[i] = pgnoNew[minI]; + apNew[i] = apNew[minI]; + pgnoNew[minI] = t; + apNew[minI] = pT; + } + } + TRACE(("BALANCE: old: %d %d %d new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", + pgnoOld[0], + nOld>=2 ? pgnoOld[1] : 0, + nOld>=3 ? pgnoOld[2] : 0, + pgnoNew[0], szNew[0], + nNew>=2 ? pgnoNew[1] : 0, nNew>=2 ? szNew[1] : 0, + nNew>=3 ? pgnoNew[2] : 0, nNew>=3 ? szNew[2] : 0, + nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0, + nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0)); + + /* + ** Evenly distribute the data in apCell[] across the new pages. + ** Insert divider cells into pParent as necessary. + */ + j = 0; + for(i=0; ipgno==pgnoNew[i] ); + assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); + assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) ); + assert( pNew->nOverflow==0 ); + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If this is an auto-vacuum database, update the pointer map entries + ** that point to the siblings that were rearranged. These can be: left + ** children of cells, the right-child of the page, or overflow pages + ** pointed to by cells. + */ + if( pBt->autoVacuum ){ + for(k=j; kpgno!=pNew->pgno ){ + rc = ptrmapPutOvfl(pNew, k-j); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + } + } +#endif + + j = cntNew[i]; + + /* If the sibling page assembled above was not the right-most sibling, + ** insert a divider cell into the parent page. + */ + if( ileaf ){ + memcpy(&pNew->aData[8], pCell, 4); + pTemp = 0; + }else if( leafData ){ + /* If the tree is a leaf-data tree, and the siblings are leaves, + ** then there is no divider cell in apCell[]. Instead, the divider + ** cell consists of the integer key for the right-most cell of + ** the sibling-page assembled above only. + */ + CellInfo info; + j--; + sqlite3BtreeParseCellPtr(pNew, apCell[j], &info); + pCell = &aSpace[iSpace]; + fillInCell(pParent, pCell, 0, info.nKey, 0, 0, 0, &sz); + iSpace += sz; + assert( iSpace<=pBt->pageSize*5 ); + pTemp = 0; + }else{ + pCell -= 4; + pTemp = &aSpace[iSpace]; + iSpace += sz; + assert( iSpace<=pBt->pageSize*5 ); + /* Obscure case for non-leaf-data trees: If the cell at pCell was + ** previously stored on a leaf node, and its reported size was 4 + ** bytes, then it may actually be smaller than this + ** (see sqlite3BtreeParseCellPtr(), 4 bytes is the minimum size of + ** any cell). But it is important to pass the correct size to + ** insertCell(), so reparse the cell now. + ** + ** Note that this can never happen in an SQLite data file, as all + ** cells are at least 4 bytes. It only happens in b-trees used + ** to evaluate "IN (SELECT ...)" and similar clauses. + */ + if( szCell[j]==4 ){ + assert(leafCorrection==4); + sz = cellSizePtr(pParent, pCell); + } + } + rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); + if( rc!=SQLITE_OK ) goto balance_cleanup; + put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If this is an auto-vacuum database, and not a leaf-data tree, + ** then update the pointer map with an entry for the overflow page + ** that the cell just inserted points to (if any). + */ + if( pBt->autoVacuum && !leafData ){ + rc = ptrmapPutOvfl(pParent, nxDiv); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } +#endif + j++; + nxDiv++; + } + } + assert( j==nCell ); + assert( nOld>0 ); + assert( nNew>0 ); + if( (pageFlags & PTF_LEAF)==0 ){ + memcpy(&apNew[nNew-1]->aData[8], &apCopy[nOld-1]->aData[8], 4); + } + if( nxDiv==pParent->nCell+pParent->nOverflow ){ + /* Right-most sibling is the right-most child of pParent */ + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew[nNew-1]); + }else{ + /* Right-most sibling is the left child of the first entry in pParent + ** past the right-most divider entry */ + put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]); + } + + /* + ** Reparent children of all cells. + */ + for(i=0; iisInit ); + rc = balance(pParent, 0); + + /* + ** Cleanup before returning. + */ +balance_cleanup: + sqlite3_free(apCell); + for(i=0; ipgno, nOld, nNew, nCell)); + return rc; +} + +/* +** This routine is called for the root page of a btree when the root +** page contains no cells. This is an opportunity to make the tree +** shallower by one level. +*/ +static int balance_shallower(MemPage *pPage){ + MemPage *pChild; /* The only child page of pPage */ + Pgno pgnoChild; /* Page number for pChild */ + int rc = SQLITE_OK; /* Return code from subprocedures */ + BtShared *pBt; /* The main BTree structure */ + int mxCellPerPage; /* Maximum number of cells per page */ + u8 **apCell; /* All cells from pages being balanced */ + int *szCell; /* Local size of all cells */ + + assert( pPage->pParent==0 ); + assert( pPage->nCell==0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + pBt = pPage->pBt; + mxCellPerPage = MX_CELL(pBt); + apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(int)) ); + if( apCell==0 ) return SQLITE_NOMEM; + szCell = (int*)&apCell[mxCellPerPage]; + if( pPage->leaf ){ + /* The table is completely empty */ + TRACE(("BALANCE: empty table %d\n", pPage->pgno)); + }else{ + /* The root page is empty but has one child. Transfer the + ** information from that one child into the root page if it + ** will fit. This reduces the depth of the tree by one. + ** + ** If the root page is page 1, it has less space available than + ** its child (due to the 100 byte header that occurs at the beginning + ** of the database fle), so it might not be able to hold all of the + ** information currently contained in the child. If this is the + ** case, then do not do the transfer. Leave page 1 empty except + ** for the right-pointer to the child page. The child page becomes + ** the virtual root of the tree. + */ + pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); + assert( pgnoChild>0 ); + assert( pgnoChild<=sqlite3PagerPagecount(pPage->pBt->pPager) ); + rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0); + if( rc ) goto end_shallow_balance; + if( pPage->pgno==1 ){ + rc = sqlite3BtreeInitPage(pChild, pPage); + if( rc ) goto end_shallow_balance; + assert( pChild->nOverflow==0 ); + if( pChild->nFree>=100 ){ + /* The child information will fit on the root page, so do the + ** copy */ + int i; + zeroPage(pPage, pChild->aData[0]); + for(i=0; inCell; i++){ + apCell[i] = findCell(pChild,i); + szCell[i] = cellSizePtr(pChild, apCell[i]); + } + assemblePage(pPage, pChild->nCell, apCell, szCell); + /* Copy the right-pointer of the child to the parent. */ + put4byte(&pPage->aData[pPage->hdrOffset+8], + get4byte(&pChild->aData[pChild->hdrOffset+8])); + freePage(pChild); + TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno)); + }else{ + /* The child has more information that will fit on the root. + ** The tree is already balanced. Do nothing. */ + TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno)); + } + }else{ + memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize); + pPage->isInit = 0; + pPage->pParent = 0; + rc = sqlite3BtreeInitPage(pPage, 0); + assert( rc==SQLITE_OK ); + freePage(pChild); + TRACE(("BALANCE: transfer child %d into root %d\n", + pChild->pgno, pPage->pgno)); + } + rc = reparentChildPages(pPage); + assert( pPage->nOverflow==0 ); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + int i; + for(i=0; inCell; i++){ + rc = ptrmapPutOvfl(pPage, i); + if( rc!=SQLITE_OK ){ + goto end_shallow_balance; + } + } + } +#endif + releasePage(pChild); + } +end_shallow_balance: + sqlite3_free(apCell); + return rc; +} + + +/* +** The root page is overfull +** +** When this happens, Create a new child page and copy the +** contents of the root into the child. Then make the root +** page an empty page with rightChild pointing to the new +** child. Finally, call balance_internal() on the new child +** to cause it to split. +*/ +static int balance_deeper(MemPage *pPage){ + int rc; /* Return value from subprocedures */ + MemPage *pChild; /* Pointer to a new child page */ + Pgno pgnoChild; /* Page number of the new child page */ + BtShared *pBt; /* The BTree */ + int usableSize; /* Total usable size of a page */ + u8 *data; /* Content of the parent page */ + u8 *cdata; /* Content of the child page */ + int hdr; /* Offset to page header in parent */ + int brk; /* Offset to content of first cell in parent */ + + assert( pPage->pParent==0 ); + assert( pPage->nOverflow>0 ); + pBt = pPage->pBt; + assert( sqlite3_mutex_held(pBt->mutex) ); + rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); + if( rc ) return rc; + assert( sqlite3PagerIswriteable(pChild->pDbPage) ); + usableSize = pBt->usableSize; + data = pPage->aData; + hdr = pPage->hdrOffset; + brk = get2byte(&data[hdr+5]); + cdata = pChild->aData; + memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); + memcpy(&cdata[brk], &data[brk], usableSize-brk); + assert( pChild->isInit==0 ); + rc = sqlite3BtreeInitPage(pChild, pPage); + if( rc ) goto balancedeeper_out; + memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0])); + pChild->nOverflow = pPage->nOverflow; + if( pChild->nOverflow ){ + pChild->nFree = 0; + } + assert( pChild->nCell==pPage->nCell ); + zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF); + put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild); + TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno)); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + int i; + rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno); + if( rc ) goto balancedeeper_out; + for(i=0; inCell; i++){ + rc = ptrmapPutOvfl(pChild, i); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } +#endif + rc = balance_nonroot(pChild); + +balancedeeper_out: + releasePage(pChild); + return rc; +} + +/* +** Decide if the page pPage needs to be balanced. If balancing is +** required, call the appropriate balancing routine. +*/ +static int balance(MemPage *pPage, int insert){ + int rc = SQLITE_OK; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); + if( pPage->pParent==0 ){ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc==SQLITE_OK && pPage->nOverflow>0 ){ + rc = balance_deeper(pPage); + } + if( rc==SQLITE_OK && pPage->nCell==0 ){ + rc = balance_shallower(pPage); + } + }else{ + if( pPage->nOverflow>0 || + (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ + rc = balance_nonroot(pPage); + } + } + return rc; +} + +/* +** This routine checks all cursors that point to table pgnoRoot. +** If any of those cursors were opened with wrFlag==0 in a different +** database connection (a database connection that shares the pager +** cache with the current connection) and that other connection +** is not in the ReadUncommmitted state, then this routine returns +** SQLITE_LOCKED. +** +** In addition to checking for read-locks (where a read-lock +** means a cursor opened with wrFlag==0) this routine also moves +** all write cursors so that they are pointing to the +** first Cell on the root page. This is necessary because an insert +** or delete might change the number of cells on a page or delete +** a page entirely and we do not want to leave any cursors +** pointing to non-existant pages or cells. +*/ +static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ + BtCursor *p; + BtShared *pBt = pBtree->pBt; + sqlite3 *db = pBtree->db; + assert( sqlite3BtreeHoldsMutex(pBtree) ); + for(p=pBt->pCursor; p; p=p->pNext){ + if( p==pExclude ) continue; + if( p->eState!=CURSOR_VALID ) continue; + if( p->pgnoRoot!=pgnoRoot ) continue; + if( p->wrFlag==0 ){ + sqlite3 *dbOther = p->pBtree->db; + if( dbOther==0 || + (dbOther!=db && (dbOther->flags & SQLITE_ReadUncommitted)==0) ){ + return SQLITE_LOCKED; + } + }else if( p->pPage->pgno!=p->pgnoRoot ){ + moveToRoot(p); + } + } + return SQLITE_OK; +} + +/* +** Insert a new record into the BTree. The key is given by (pKey,nKey) +** and the data is given by (pData,nData). The cursor is used only to +** define what table the record should be inserted into. The cursor +** is left pointing at a random location. +** +** For an INTKEY table, only the nKey value of the key is used. pKey is +** ignored. For a ZERODATA table, the pData and nData are both ignored. +*/ +int sqlite3BtreeInsert( + BtCursor *pCur, /* Insert data into the table of this cursor */ + const void *pKey, i64 nKey, /* The key of the new record */ + const void *pData, int nData, /* The data of the new record */ + int nZero, /* Number of extra 0 bytes to append to data */ + int appendBias /* True if this is likely an append */ +){ + int rc; + int loc; + int szNew; + MemPage *pPage; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + unsigned char *oldCell; + unsigned char *newCell = 0; + + assert( cursorHoldsMutex(pCur) ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction before doing an insert */ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + return rc; + } + assert( !pBt->readOnly ); + if( !pCur->wrFlag ){ + return SQLITE_PERM; /* Cursor not open for writing */ + } + if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + + /* Save the positions of any other cursors open on this table */ + clearCursorPosition(pCur); + if( + SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) + ){ + return rc; + } + + pPage = pCur->pPage; + assert( pPage->intKey || nKey>=0 ); + assert( pPage->leaf || !pPage->leafData ); + TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", + pCur->pgnoRoot, nKey, nData, pPage->pgno, + loc==0 ? "overwrite" : "new entry")); + assert( pPage->isInit ); + newCell = sqlite3_malloc( MX_CELL_SIZE(pBt) ); + if( newCell==0 ) return SQLITE_NOMEM; + rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); + if( rc ) goto end_insert; + assert( szNew==cellSizePtr(pPage, newCell) ); + assert( szNew<=MX_CELL_SIZE(pBt) ); + if( loc==0 && CURSOR_VALID==pCur->eState ){ + int szOld; + assert( pCur->idx>=0 && pCur->idxnCell ); + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ){ + goto end_insert; + } + oldCell = findCell(pPage, pCur->idx); + if( !pPage->leaf ){ + memcpy(newCell, oldCell, 4); + } + szOld = cellSizePtr(pPage, oldCell); + rc = clearCell(pPage, oldCell); + if( rc ) goto end_insert; + dropCell(pPage, pCur->idx, szOld); + }else if( loc<0 && pPage->nCell>0 ){ + assert( pPage->leaf ); + pCur->idx++; + pCur->info.nSize = 0; + }else{ + assert( pPage->leaf ); + } + rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0); + if( rc!=SQLITE_OK ) goto end_insert; + rc = balance(pPage, 1); + /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ + /* fflush(stdout); */ + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } +end_insert: + sqlite3_free(newCell); + return rc; +} + +/* +** Delete the entry that the cursor is pointing to. The cursor +** is left pointing at a random location. +*/ +int sqlite3BtreeDelete(BtCursor *pCur){ + MemPage *pPage = pCur->pPage; + unsigned char *pCell; + int rc; + Pgno pgnoChild = 0; + Btree *p = pCur->pBtree; + BtShared *pBt = p->pBt; + + assert( cursorHoldsMutex(pCur) ); + assert( pPage->isInit ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction before doing a delete */ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + return rc; + } + assert( !pBt->readOnly ); + if( pCur->eState==CURSOR_FAULT ){ + return pCur->skip; + } + if( pCur->idx >= pPage->nCell ){ + return SQLITE_ERROR; /* The cursor is not pointing to anything */ + } + if( !pCur->wrFlag ){ + return SQLITE_PERM; /* Did not open this cursor for writing */ + } + if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + + /* Restore the current cursor position (a no-op if the cursor is not in + ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors + ** open on the same table. Then call sqlite3PagerWrite() on the page + ** that the entry will be deleted from. + */ + if( + (rc = restoreOrClearCursorPosition(pCur))!=0 || + (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || + (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 + ){ + return rc; + } + + /* Locate the cell within its page and leave pCell pointing to the + ** data. The clearCell() call frees any overflow pages associated with the + ** cell. The cell itself is still intact. + */ + pCell = findCell(pPage, pCur->idx); + if( !pPage->leaf ){ + pgnoChild = get4byte(pCell); + } + rc = clearCell(pPage, pCell); + if( rc ){ + return rc; + } + + if( !pPage->leaf ){ + /* + ** The entry we are about to delete is not a leaf so if we do not + ** do something we will leave a hole on an internal page. + ** We have to fill the hole by moving in a cell from a leaf. The + ** next Cell after the one to be deleted is guaranteed to exist and + ** to be a leaf so we can use it. + */ + BtCursor leafCur; + unsigned char *pNext; + int notUsed; + unsigned char *tempCell = 0; + assert( !pPage->leafData ); + sqlite3BtreeGetTempCursor(pCur, &leafCur); + rc = sqlite3BtreeNext(&leafCur, ¬Used); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); + } + if( rc==SQLITE_OK ){ + int szNext; + TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", + pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); + dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); + pNext = findCell(leafCur.pPage, leafCur.idx); + szNext = cellSizePtr(leafCur.pPage, pNext); + assert( MX_CELL_SIZE(pBt)>=szNext+4 ); + tempCell = sqlite3_malloc( MX_CELL_SIZE(pBt) ); + if( tempCell==0 ){ + rc = SQLITE_NOMEM; + } + if( rc==SQLITE_OK ){ + rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0); + } + if( rc==SQLITE_OK ){ + put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); + rc = balance(pPage, 0); + } + if( rc==SQLITE_OK ){ + dropCell(leafCur.pPage, leafCur.idx, szNext); + rc = balance(leafCur.pPage, 0); + } + } + sqlite3_free(tempCell); + sqlite3BtreeReleaseTempCursor(&leafCur); + }else{ + TRACE(("DELETE: table=%d delete from leaf %d\n", + pCur->pgnoRoot, pPage->pgno)); + dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); + rc = balance(pPage, 0); + } + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } + return rc; +} + +/* +** Create a new BTree table. Write into *piTable the page +** number for the root page of the new table. +** +** The type of type is determined by the flags parameter. Only the +** following values of flags are currently in use. Other values for +** flags might not work: +** +** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys +** BTREE_ZERODATA Used for SQL indices +*/ +static int btreeCreateTable(Btree *p, int *piTable, int flags){ + BtShared *pBt = p->pBt; + MemPage *pRoot; + Pgno pgnoRoot; + int rc; + + assert( sqlite3BtreeHoldsMutex(p) ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction first */ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + return rc; + } + assert( !pBt->readOnly ); + +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ){ + return rc; + } +#else + if( pBt->autoVacuum ){ + Pgno pgnoMove; /* Move a page here to make room for the root-page */ + MemPage *pPageMove; /* The page to move to. */ + + /* Creating a new table may probably require moving an existing database + ** to make room for the new tables root page. In case this page turns + ** out to be an overflow page, delete all overflow page-map caches + ** held by open cursors. + */ + invalidateAllOverflowCache(pBt); + + /* Read the value of meta[3] from the database to determine where the + ** root page of the new table should go. meta[3] is the largest root-page + ** created so far, so the new root-page is (meta[3]+1). + */ + rc = sqlite3BtreeGetMeta(p, 4, &pgnoRoot); + if( rc!=SQLITE_OK ){ + return rc; + } + pgnoRoot++; + + /* The new root-page may not be allocated on a pointer-map page, or the + ** PENDING_BYTE page. + */ + while( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || + pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ + pgnoRoot++; + } + assert( pgnoRoot>=3 ); + + /* Allocate a page. The page that currently resides at pgnoRoot will + ** be moved to the allocated page (unless the allocated page happens + ** to reside at pgnoRoot). + */ + rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + + if( pgnoMove!=pgnoRoot ){ + /* pgnoRoot is the page that will be used for the root-page of + ** the new table (assuming an error did not occur). But we were + ** allocated pgnoMove. If required (i.e. if it was not allocated + ** by extending the file), the current page at position pgnoMove + ** is already journaled. + */ + u8 eType; + Pgno iPtrPage; + + releasePage(pPageMove); + + /* Move the page currently at pgnoRoot to pgnoMove. */ + rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); + if( rc!=SQLITE_OK || eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ + releasePage(pRoot); + return rc; + } + assert( eType!=PTRMAP_ROOTPAGE ); + assert( eType!=PTRMAP_FREEPAGE ); + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove); + releasePage(pRoot); + + /* Obtain the page at pgnoRoot */ + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + }else{ + pRoot = pPageMove; + } + + /* Update the pointer-map and meta-data with the new root-page number. */ + rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); + if( rc ){ + releasePage(pRoot); + return rc; + } + rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); + if( rc ){ + releasePage(pRoot); + return rc; + } + + }else{ + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ) return rc; + } +#endif + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + zeroPage(pRoot, flags | PTF_LEAF); + sqlite3PagerUnref(pRoot->pDbPage); + *piTable = (int)pgnoRoot; + return SQLITE_OK; +} +int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->db = p->db; + rc = btreeCreateTable(p, piTable, flags); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Erase the given database page and all its children. Return +** the page to the freelist. +*/ +static int clearDatabasePage( + BtShared *pBt, /* The BTree that contains the table */ + Pgno pgno, /* Page number to clear */ + MemPage *pParent, /* Parent page. NULL for the root */ + int freePageFlag /* Deallocate page if true */ +){ + MemPage *pPage = 0; + int rc; + unsigned char *pCell; + int i; + + assert( sqlite3_mutex_held(pBt->mutex) ); + if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + rc = getAndInitPage(pBt, pgno, &pPage, pParent); + if( rc ) goto cleardatabasepage_out; + for(i=0; inCell; i++){ + pCell = findCell(pPage, i); + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1); + if( rc ) goto cleardatabasepage_out; + } + rc = clearCell(pPage, pCell); + if( rc ) goto cleardatabasepage_out; + } + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1); + if( rc ) goto cleardatabasepage_out; + } + if( freePageFlag ){ + rc = freePage(pPage); + }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ + zeroPage(pPage, pPage->aData[0] | PTF_LEAF); + } + +cleardatabasepage_out: + releasePage(pPage); + return rc; +} + +/* +** Delete all information from a single table in the database. iTable is +** the page number of the root of the table. After this routine returns, +** the root page is empty, but still exists. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** read cursors on the table. Open write cursors are moved to the +** root of the table. +*/ +int sqlite3BtreeClearTable(Btree *p, int iTable){ + int rc; + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( p->inTrans!=TRANS_WRITE ){ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + }else if( (rc = checkReadLocks(p, iTable, 0))!=SQLITE_OK ){ + /* nothing to do */ + }else if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ + /* nothing to do */ + }else{ + rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Erase all information in a table and add the root of the table to +** the freelist. Except, the root of the principle table (the one on +** page 1) is never added to the freelist. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** cursors on the table. +** +** If AUTOVACUUM is enabled and the page at iTable is not the last +** root page in the database file, then the last root page +** in the database file is moved into the slot formerly occupied by +** iTable and that last slot formerly occupied by the last root page +** is added to the freelist instead of iTable. In this say, all +** root pages are kept at the beginning of the database file, which +** is necessary for AUTOVACUUM to work right. *piMoved is set to the +** page number that used to be the last root page in the file before +** the move. If no page gets moved, *piMoved is set to 0. +** The last root page is recorded in meta[3] and the value of +** meta[3] is updated by this procedure. +*/ +static int btreeDropTable(Btree *p, int iTable, int *piMoved){ + int rc; + MemPage *pPage = 0; + BtShared *pBt = p->pBt; + + assert( sqlite3BtreeHoldsMutex(p) ); + if( p->inTrans!=TRANS_WRITE ){ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + + /* It is illegal to drop a table if any cursors are open on the + ** database. This is because in auto-vacuum mode the backend may + ** need to move another root-page to fill a gap left by the deleted + ** root page. If an open cursor was using this page a problem would + ** occur. + */ + if( pBt->pCursor ){ + return SQLITE_LOCKED; + } + + rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0); + if( rc ) return rc; + rc = sqlite3BtreeClearTable(p, iTable); + if( rc ){ + releasePage(pPage); + return rc; + } + + *piMoved = 0; + + if( iTable>1 ){ +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = freePage(pPage); + releasePage(pPage); +#else + if( pBt->autoVacuum ){ + Pgno maxRootPgno; + rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno); + if( rc!=SQLITE_OK ){ + releasePage(pPage); + return rc; + } + + if( iTable==maxRootPgno ){ + /* If the table being dropped is the table with the largest root-page + ** number in the database, put the root page on the free list. + */ + rc = freePage(pPage); + releasePage(pPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + /* The table being dropped does not have the largest root-page + ** number in the database. So move the page that does into the + ** gap left by the deleted root-page. + */ + MemPage *pMove; + releasePage(pPage); + rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = freePage(pMove); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + *piMoved = maxRootPgno; + } + + /* Set the new 'max-root-page' value in the database header. This + ** is the old value less one, less one more if that happens to + ** be a root-page number, less one again if that is the + ** PENDING_BYTE_PAGE. + */ + maxRootPgno--; + if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){ + maxRootPgno--; + } + if( maxRootPgno==PTRMAP_PAGENO(pBt, maxRootPgno) ){ + maxRootPgno--; + } + assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); + + rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); + }else{ + rc = freePage(pPage); + releasePage(pPage); + } +#endif + }else{ + /* If sqlite3BtreeDropTable was called on page 1. */ + zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); + releasePage(pPage); + } + return rc; +} +int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ + int rc; + sqlite3BtreeEnter(p); + p->pBt->db = p->db; + rc = btreeDropTable(p, iTable, piMoved); + sqlite3BtreeLeave(p); + return rc; +} + + +/* +** Read the meta-information out of a database file. Meta[0] +** is the number of free pages currently in the database. Meta[1] +** through meta[15] are available for use by higher layers. Meta[0] +** is read-only, the others are read/write. +** +** The schema layer numbers meta values differently. At the schema +** layer (and the SetCookie and ReadCookie opcodes) the number of +** free pages is not visible. So Cookie[0] is the same as Meta[1]. +*/ +int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ + DbPage *pDbPage; + int rc; + unsigned char *pP1; + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + + /* Reading a meta-data value requires a read-lock on page 1 (and hence + ** the sqlite_master table. We grab this lock regardless of whether or + ** not the SQLITE_ReadUncommitted flag is set (the table rooted at page + ** 1 is treated as a special case by queryTableLock() and lockTable()). + */ + rc = queryTableLock(p, 1, READ_LOCK); + if( rc!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return rc; + } + + assert( idx>=0 && idx<=15 ); + rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage); + if( rc ){ + sqlite3BtreeLeave(p); + return rc; + } + pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage); + *pMeta = get4byte(&pP1[36 + idx*4]); + sqlite3PagerUnref(pDbPage); + + /* If autovacuumed is disabled in this build but we are trying to + ** access an autovacuumed database, then make the database readonly. + */ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; +#endif + + /* Grab the read-lock on page 1. */ + rc = lockTable(p, 1, READ_LOCK); + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Write meta-information back into the database. Meta[0] is +** read-only and may not be written. +*/ +int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ + BtShared *pBt = p->pBt; + unsigned char *pP1; + int rc; + assert( idx>=1 && idx<=15 ); + sqlite3BtreeEnter(p); + pBt->db = p->db; + if( p->inTrans!=TRANS_WRITE ){ + rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + }else{ + assert( pBt->pPage1!=0 ); + pP1 = pBt->pPage1->aData; + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pP1[36 + idx*4], iMeta); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( idx==7 ){ + assert( pBt->autoVacuum || iMeta==0 ); + assert( iMeta==0 || iMeta==1 ); + pBt->incrVacuum = iMeta; + } +#endif + } + } + sqlite3BtreeLeave(p); + return rc; +} + +/* +** Return the flag byte at the beginning of the page that the cursor +** is currently pointing to. +*/ +int sqlite3BtreeFlags(BtCursor *pCur){ + /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call + ** restoreOrClearCursorPosition() here. + */ + MemPage *pPage; + restoreOrClearCursorPosition(pCur); + pPage = pCur->pPage; + assert( cursorHoldsMutex(pCur) ); + assert( pPage->pBt==pCur->pBt ); + return pPage ? pPage->aData[pPage->hdrOffset] : 0; +} + + +/* +** Return the pager associated with a BTree. This routine is used for +** testing and debugging only. +*/ +Pager *sqlite3BtreePager(Btree *p){ + return p->pBt->pPager; +} + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Append a message to the error message string. +*/ +static void checkAppendMsg( + IntegrityCk *pCheck, + char *zMsg1, + const char *zFormat, + ... +){ + va_list ap; + char *zMsg2; + if( !pCheck->mxErr ) return; + pCheck->mxErr--; + pCheck->nErr++; + va_start(ap, zFormat); + zMsg2 = sqlite3VMPrintf(0, zFormat, ap); + va_end(ap); + if( zMsg1==0 ) zMsg1 = ""; + if( pCheck->zErrMsg ){ + char *zOld = pCheck->zErrMsg; + pCheck->zErrMsg = 0; + sqlite3SetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0); + sqlite3_free(zOld); + }else{ + sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0); + } + sqlite3_free(zMsg2); +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Add 1 to the reference count for page iPage. If this is the second +** reference to the page, add an error message to pCheck->zErrMsg. +** Return 1 if there are 2 ore more references to the page and 0 if +** if this is the first reference to the page. +** +** Also check that the page number is in bounds. +*/ +static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ + if( iPage==0 ) return 1; + if( iPage>pCheck->nPage || iPage<0 ){ + checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); + return 1; + } + if( pCheck->anRef[iPage]==1 ){ + checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); + return 1; + } + return (pCheck->anRef[iPage]++)>1; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Check that the entry in the pointer-map for page iChild maps to +** page iParent, pointer type ptrType. If not, append an error message +** to pCheck. +*/ +static void checkPtrmap( + IntegrityCk *pCheck, /* Integrity check context */ + Pgno iChild, /* Child page number */ + u8 eType, /* Expected pointer map type */ + Pgno iParent, /* Expected pointer map parent page number */ + char *zContext /* Context description (used for error msg) */ +){ + int rc; + u8 ePtrmapType; + Pgno iPtrmapParent; + + rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); + if( rc!=SQLITE_OK ){ + checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild); + return; + } + + if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ + checkAppendMsg(pCheck, zContext, + "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", + iChild, eType, iParent, ePtrmapType, iPtrmapParent); + } +} +#endif + +/* +** Check the integrity of the freelist or of an overflow page list. +** Verify that the number of pages on the list is N. +*/ +static void checkList( + IntegrityCk *pCheck, /* Integrity checking context */ + int isFreeList, /* True for a freelist. False for overflow page list */ + int iPage, /* Page number for first page in the list */ + int N, /* Expected number of pages in the list */ + char *zContext /* Context for error messages */ +){ + int i; + int expected = N; + int iFirst = iPage; + while( N-- > 0 && pCheck->mxErr ){ + DbPage *pOvflPage; + unsigned char *pOvflData; + if( iPage<1 ){ + checkAppendMsg(pCheck, zContext, + "%d of %d pages missing from overflow list starting at %d", + N+1, expected, iFirst); + break; + } + if( checkRef(pCheck, iPage, zContext) ) break; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ + checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); + break; + } + pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); + if( isFreeList ){ + int n = get4byte(&pOvflData[4]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pCheck->pBt->autoVacuum ){ + checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); + } +#endif + if( n>pCheck->pBt->usableSize/4-8 ){ + checkAppendMsg(pCheck, zContext, + "freelist leaf count too big on page %d", iPage); + N--; + }else{ + for(i=0; ipBt->autoVacuum ){ + checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext); + } +#endif + checkRef(pCheck, iFreePage, zContext); + } + N -= n; + } + } +#ifndef SQLITE_OMIT_AUTOVACUUM + else{ + /* If this database supports auto-vacuum and iPage is not the last + ** page in this overflow list, check that the pointer-map entry for + ** the following page matches iPage. + */ + if( pCheck->pBt->autoVacuum && N>0 ){ + i = get4byte(pOvflData); + checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext); + } + } +#endif + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); + } +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Do various sanity checks on a single page of a tree. Return +** the tree depth. Root pages return 0. Parents of root pages +** return 1, and so forth. +** +** These checks are done: +** +** 1. Make sure that cells and freeblocks do not overlap +** but combine to completely cover the page. +** NO 2. Make sure cell keys are in order. +** NO 3. Make sure no key is less than or equal to zLowerBound. +** NO 4. Make sure no key is greater than or equal to zUpperBound. +** 5. Check the integrity of overflow pages. +** 6. Recursively call checkTreePage on all children. +** 7. Verify that the depth of all children is the same. +** 8. Make sure this page is at least 33% full or else it is +** the root of the tree. +*/ +static int checkTreePage( + IntegrityCk *pCheck, /* Context for the sanity check */ + int iPage, /* Page number of the page to check */ + MemPage *pParent, /* Parent page */ + char *zParentContext /* Parent context */ +){ + MemPage *pPage; + int i, rc, depth, d2, pgno, cnt; + int hdr, cellStart; + int nCell; + u8 *data; + BtShared *pBt; + int usableSize; + char zContext[100]; + char *hit; + + sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); + + /* Check that the page exists + */ + pBt = pCheck->pBt; + usableSize = pBt->usableSize; + if( iPage==0 ) return 0; + if( checkRef(pCheck, iPage, zParentContext) ) return 0; + if( (rc = sqlite3BtreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ + checkAppendMsg(pCheck, zContext, + "unable to get the page. error code=%d", rc); + return 0; + } + if( (rc = sqlite3BtreeInitPage(pPage, pParent))!=0 ){ + checkAppendMsg(pCheck, zContext, + "sqlite3BtreeInitPage() returns error code %d", rc); + releasePage(pPage); + return 0; + } + + /* Check out all the cells. + */ + depth = 0; + for(i=0; inCell && pCheck->mxErr; i++){ + u8 *pCell; + int sz; + CellInfo info; + + /* Check payload overflow pages + */ + sqlite3_snprintf(sizeof(zContext), zContext, + "On tree page %d cell %d: ", iPage, i); + pCell = findCell(pPage,i); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + sz = info.nData; + if( !pPage->intKey ) sz += info.nKey; + assert( sz==info.nPayload ); + if( sz>info.nLocal ){ + int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext); + } +#endif + checkList(pCheck, 0, pgnoOvfl, nPage, zContext); + } + + /* Check sanity of left child page. + */ + if( !pPage->leaf ){ + pgno = get4byte(pCell); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); + } +#endif + d2 = checkTreePage(pCheck,pgno,pPage,zContext); + if( i>0 && d2!=depth ){ + checkAppendMsg(pCheck, zContext, "Child page depth differs"); + } + depth = d2; + } + } + if( !pPage->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + sqlite3_snprintf(sizeof(zContext), zContext, + "On page %d at right child: ", iPage); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); + } +#endif + checkTreePage(pCheck, pgno, pPage, zContext); + } + + /* Check for complete coverage of the page + */ + data = pPage->aData; + hdr = pPage->hdrOffset; + hit = sqlite3MallocZero( usableSize ); + if( hit ){ + memset(hit, 1, get2byte(&data[hdr+5])); + nCell = get2byte(&data[hdr+3]); + cellStart = hdr + 12 - 4*pPage->leaf; + for(i=0; i=usableSize || pc<0 ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage,0); + }else{ + for(j=pc+size-1; j>=pc; j--) hit[j]++; + } + } + for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i=usableSize || i<0 ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage,0); + }else{ + for(j=i+size-1; j>=i; j--) hit[j]++; + } + i = get2byte(&data[i]); + } + for(i=cnt=0; i1 ){ + checkAppendMsg(pCheck, 0, + "Multiple uses for byte %d of page %d", i, iPage); + break; + } + } + if( cnt!=data[hdr+7] ){ + checkAppendMsg(pCheck, 0, + "Fragmented space is %d byte reported as %d on page %d", + cnt, data[hdr+7], iPage); + } + } + sqlite3_free(hit); + + releasePage(pPage); + return depth+1; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** This routine does a complete check of the given BTree file. aRoot[] is +** an array of pages numbers were each page number is the root page of +** a table. nRoot is the number of entries in aRoot. +** +** If everything checks out, this routine returns NULL. If something is +** amiss, an error message is written into memory obtained from malloc() +** and a pointer to that error message is returned. The calling function +** is responsible for freeing the error message when it is done. +*/ +char *sqlite3BtreeIntegrityCheck( + Btree *p, /* The btree to be checked */ + int *aRoot, /* An array of root pages numbers for individual trees */ + int nRoot, /* Number of entries in aRoot[] */ + int mxErr, /* Stop reporting errors after this many */ + int *pnErr /* Write number of errors seen to this variable */ +){ + int i; + int nRef; + IntegrityCk sCheck; + BtShared *pBt = p->pBt; + + sqlite3BtreeEnter(p); + pBt->db = p->db; + nRef = sqlite3PagerRefcount(pBt->pPager); + if( lockBtreeWithRetry(p)!=SQLITE_OK ){ + sqlite3BtreeLeave(p); + return sqlite3StrDup("Unable to acquire a read lock on the database"); + } + sCheck.pBt = pBt; + sCheck.pPager = pBt->pPager; + sCheck.nPage = sqlite3PagerPagecount(sCheck.pPager); + sCheck.mxErr = mxErr; + sCheck.nErr = 0; + *pnErr = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->nTrunc!=0 ){ + sCheck.nPage = pBt->nTrunc; + } +#endif + if( sCheck.nPage==0 ){ + unlockBtreeIfUnused(pBt); + sqlite3BtreeLeave(p); + return 0; + } + sCheck.anRef = sqlite3_malloc( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); + if( !sCheck.anRef ){ + unlockBtreeIfUnused(pBt); + *pnErr = 1; + sqlite3BtreeLeave(p); + return sqlite3MPrintf(p->db, "Unable to malloc %d bytes", + (sCheck.nPage+1)*sizeof(sCheck.anRef[0])); + } + for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } + i = PENDING_BYTE_PAGE(pBt); + if( i<=sCheck.nPage ){ + sCheck.anRef[i] = 1; + } + sCheck.zErrMsg = 0; + + /* Check the integrity of the freelist + */ + checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), + get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); + + /* Check all the tables. + */ + for(i=0; iautoVacuum && aRoot[i]>1 ){ + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); + } +#endif + checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: "); + } + + /* Make sure every page in the file is referenced + */ + for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( sCheck.anRef[i]==0 ){ + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); + } +#else + /* If the database supports auto-vacuum, make sure no tables contain + ** references to pointer-map pages. + */ + if( sCheck.anRef[i]==0 && + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); + } + if( sCheck.anRef[i]!=0 && + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); + } +#endif + } + + /* Make sure this analysis did not leave any unref() pages + */ + unlockBtreeIfUnused(pBt); + if( nRef != sqlite3PagerRefcount(pBt->pPager) ){ + checkAppendMsg(&sCheck, 0, + "Outstanding page count goes from %d to %d during this analysis", + nRef, sqlite3PagerRefcount(pBt->pPager) + ); + } + + /* Clean up and report errors. + */ + sqlite3BtreeLeave(p); + sqlite3_free(sCheck.anRef); + *pnErr = sCheck.nErr; + return sCheck.zErrMsg; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* +** Return the full pathname of the underlying database file. +** +** The pager filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +const char *sqlite3BtreeGetFilename(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerFilename(p->pBt->pPager); +} + +/* +** Return the pathname of the directory that contains the database file. +** +** The pager directory name is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +const char *sqlite3BtreeGetDirname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerDirname(p->pBt->pPager); +} + +/* +** Return the pathname of the journal file for this database. The return +** value of this routine is the same regardless of whether the journal file +** has been created or not. +** +** The pager journal filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. +*/ +const char *sqlite3BtreeGetJournalname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerJournalname(p->pBt->pPager); +} + +#ifndef SQLITE_OMIT_VACUUM +/* +** Copy the complete content of pBtFrom into pBtTo. A transaction +** must be active for both files. +** +** The size of file pBtFrom may be reduced by this operation. +** If anything goes wrong, the transaction on pBtFrom is rolled back. +*/ +static int btreeCopyFile(Btree *pTo, Btree *pFrom){ + int rc = SQLITE_OK; + Pgno i, nPage, nToPage, iSkip; + + BtShared *pBtTo = pTo->pBt; + BtShared *pBtFrom = pFrom->pBt; + pBtTo->db = pTo->db; + pBtFrom->db = pFrom->db; + + + if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ + return SQLITE_ERROR; + } + if( pBtTo->pCursor ) return SQLITE_BUSY; + nToPage = sqlite3PagerPagecount(pBtTo->pPager); + nPage = sqlite3PagerPagecount(pBtFrom->pPager); + iSkip = PENDING_BYTE_PAGE(pBtTo); + for(i=1; rc==SQLITE_OK && i<=nPage; i++){ + DbPage *pDbPage; + if( i==iSkip ) continue; + rc = sqlite3PagerGet(pBtFrom->pPager, i, &pDbPage); + if( rc ) break; + rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage)); + sqlite3PagerUnref(pDbPage); + } + + /* If the file is shrinking, journal the pages that are being truncated + ** so that they can be rolled back if the commit fails. + */ + for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ + DbPage *pDbPage; + if( i==iSkip ) continue; + rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); + if( rc ) break; + rc = sqlite3PagerWrite(pDbPage); + sqlite3PagerDontWrite(pDbPage); + /* Yeah. It seems wierd to call DontWrite() right after Write(). But + ** that is because the names of those procedures do not exactly + ** represent what they do. Write() really means "put this page in the + ** rollback journal and mark it as dirty so that it will be written + ** to the database file later." DontWrite() undoes the second part of + ** that and prevents the page from being written to the database. The + ** page is still on the rollback journal, though. And that is the whole + ** point of this loop: to put pages on the rollback journal. */ + sqlite3PagerUnref(pDbPage); + } + if( !rc && nPagepPager, nPage); + } + + if( rc ){ + sqlite3BtreeRollback(pTo); + } + return rc; +} +int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ + int rc; + sqlite3BtreeEnter(pTo); + sqlite3BtreeEnter(pFrom); + rc = btreeCopyFile(pTo, pFrom); + sqlite3BtreeLeave(pFrom); + sqlite3BtreeLeave(pTo); + return rc; +} + +#endif /* SQLITE_OMIT_VACUUM */ + +/* +** Return non-zero if a transaction is active. +*/ +int sqlite3BtreeIsInTrans(Btree *p){ + assert( p==0 || sqlite3_mutex_held(p->db->mutex) ); + return (p && (p->inTrans==TRANS_WRITE)); +} + +/* +** Return non-zero if a statement transaction is active. +*/ +int sqlite3BtreeIsInStmt(Btree *p){ + assert( sqlite3BtreeHoldsMutex(p) ); + return (p->pBt && p->pBt->inStmt); +} + +/* +** Return non-zero if a read (or write) transaction is active. +*/ +int sqlite3BtreeIsInReadTrans(Btree *p){ + assert( sqlite3_mutex_held(p->db->mutex) ); + return (p && (p->inTrans!=TRANS_NONE)); +} + +/* +** This function returns a pointer to a blob of memory associated with +** a single shared-btree. The memory is used by client code for its own +** purposes (for example, to store a high-level schema associated with +** the shared-btree). The btree layer manages reference counting issues. +** +** The first time this is called on a shared-btree, nBytes bytes of memory +** are allocated, zeroed, and returned to the caller. For each subsequent +** call the nBytes parameter is ignored and a pointer to the same blob +** of memory returned. +** +** Just before the shared-btree is closed, the function passed as the +** xFree argument when the memory allocation was made is invoked on the +** blob of allocated memory. This function should not call sqlite3_free() +** on the memory, the btree layer does that. +*/ +void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ + BtShared *pBt = p->pBt; + sqlite3BtreeEnter(p); + if( !pBt->pSchema ){ + pBt->pSchema = sqlite3MallocZero(nBytes); + pBt->xFreeSchema = xFree; + } + sqlite3BtreeLeave(p); + return pBt->pSchema; +} + +/* +** Return true if another user of the same shared btree as the argument +** handle holds an exclusive lock on the sqlite_master table. +*/ +int sqlite3BtreeSchemaLocked(Btree *p){ + int rc; + assert( sqlite3_mutex_held(p->db->mutex) ); + sqlite3BtreeEnter(p); + rc = (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); + sqlite3BtreeLeave(p); + return rc; +} + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Obtain a lock on the table whose root page is iTab. The +** lock is a write lock if isWritelock is true or a read lock +** if it is false. +*/ +int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ + int rc = SQLITE_OK; + u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK); + sqlite3BtreeEnter(p); + rc = queryTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = lockTable(p, iTab, lockType); + } + sqlite3BtreeLeave(p); + return rc; +} +#endif + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Argument pCsr must be a cursor opened for writing on an +** INTKEY table currently pointing at a valid table entry. +** This function modifies the data stored as part of that entry. +** Only the data content may only be modified, it is not possible +** to change the length of the data stored. +*/ +int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ + assert( cursorHoldsMutex(pCsr) ); + assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) ); + assert(pCsr->isIncrblobHandle); + if( pCsr->eState>=CURSOR_REQUIRESEEK ){ + if( pCsr->eState==CURSOR_FAULT ){ + return pCsr->skip; + }else{ + return SQLITE_ABORT; + } + } + + /* Check some preconditions: + ** (a) the cursor is open for writing, + ** (b) there is no read-lock on the table being modified and + ** (c) the cursor points at a valid row of an intKey table. + */ + if( !pCsr->wrFlag ){ + return SQLITE_READONLY; + } + assert( !pCsr->pBt->readOnly + && pCsr->pBt->inTransaction==TRANS_WRITE ); + if( checkReadLocks(pCsr->pBtree, pCsr->pgnoRoot, pCsr) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + if( pCsr->eState==CURSOR_INVALID || !pCsr->pPage->intKey ){ + return SQLITE_ERROR; + } + + return accessPayload(pCsr, offset, amt, (unsigned char *)z, 0, 1); +} + +/* +** Set a flag on this cursor to cache the locations of pages from the +** overflow list for the current row. This is used by cursors opened +** for incremental blob IO only. +** +** This function sets a flag only. The actual page location cache +** (stored in BtCursor.aOverflow[]) is allocated and used by function +** accessPayload() (the worker function for sqlite3BtreeData() and +** sqlite3BtreePutData()). +*/ +void sqlite3BtreeCacheOverflow(BtCursor *pCur){ + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + assert(!pCur->isIncrblobHandle); + assert(!pCur->aOverflow); + pCur->isIncrblobHandle = 1; +} +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/btree.h b/client/src/thirdparty/sqlite-3.4.2/src/btree.h new file mode 100644 index 0000000..3bfebdb --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/btree.h @@ -0,0 +1,203 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This header file defines the interface that the sqlite B-Tree file +** subsystem. See comments in the source code for a detailed description +** of what each interface routine does. +** +** @(#) $Id: btree.h,v 1.94 2007/12/07 18:55:28 drh Exp $ +*/ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +/* TODO: This definition is just included so other modules compile. It +** needs to be revisited. +*/ +#define SQLITE_N_BTREE_META 10 + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_AUTOVACUUM + #define SQLITE_DEFAULT_AUTOVACUUM 0 +#endif + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; +typedef struct BtreeMutexArray BtreeMutexArray; + +/* +** This structure records all of the Btrees that need to hold +** a mutex before we enter sqlite3VdbeExec(). The Btrees are +** are placed in aBtree[] in order of aBtree[]->pBt. That way, +** we can always lock and unlock them all quickly. +*/ +struct BtreeMutexArray { + int nMutex; + Btree *aBtree[SQLITE_MAX_ATTACHED+1]; +}; + + +int sqlite3BtreeOpen( + const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ + Btree **, /* Return open Btree* here */ + int flags, /* Flags */ + int vfsFlags /* Flags passed through to VFS open */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +** +** NOTE: These values must match the corresponding PAGER_ values in +** pager.h. +*/ +#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */ +#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ +#define BTREE_MEMORY 4 /* In-memory DB. No argument */ +#define BTREE_READONLY 8 /* Open the database in read-only mode */ +#define BTREE_READWRITE 16 /* Open for both reading and writing */ +#define BTREE_CREATE 32 /* Create the database if it does not exist */ + +/* Additional values for the 4th argument of sqlite3BtreeOpen that +** are not associated with PAGER_ values. +*/ +#define BTREE_PRIVATE 64 /* Never share with other connections */ + +int sqlite3BtreeClose(Btree*); +int sqlite3BtreeSetCacheSize(Btree*,int); +int sqlite3BtreeSetSafetyLevel(Btree*,int,int); +int sqlite3BtreeSyncDisabled(Btree*); +int sqlite3BtreeSetPageSize(Btree*,int,int); +int sqlite3BtreeGetPageSize(Btree*); +int sqlite3BtreeMaxPageCount(Btree*,int); +int sqlite3BtreeGetReserve(Btree*); +int sqlite3BtreeSetAutoVacuum(Btree *, int); +int sqlite3BtreeGetAutoVacuum(Btree *); +int sqlite3BtreeBeginTrans(Btree*,int); +int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +int sqlite3BtreeCommitPhaseTwo(Btree*); +int sqlite3BtreeCommit(Btree*); +int sqlite3BtreeRollback(Btree*); +int sqlite3BtreeBeginStmt(Btree*); +int sqlite3BtreeCommitStmt(Btree*); +int sqlite3BtreeRollbackStmt(Btree*); +int sqlite3BtreeCreateTable(Btree*, int*, int flags); +int sqlite3BtreeIsInTrans(Btree*); +int sqlite3BtreeIsInStmt(Btree*); +int sqlite3BtreeIsInReadTrans(Btree*); +void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +int sqlite3BtreeSchemaLocked(Btree *); +int sqlite3BtreeLockTable(Btree *, int, u8); + +const char *sqlite3BtreeGetFilename(Btree *); +const char *sqlite3BtreeGetDirname(Btree *); +const char *sqlite3BtreeGetJournalname(Btree *); +int sqlite3BtreeCopyFile(Btree *, Btree *); + +int sqlite3BtreeIncrVacuum(Btree *); + +/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR +** of the following flags: +*/ +#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ +#define BTREE_ZERODATA 2 /* Table has keys only - no data */ +#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */ + +int sqlite3BtreeDropTable(Btree*, int, int*); +int sqlite3BtreeClearTable(Btree*, int); +int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); +int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); +void sqlite3BtreeTripAllCursors(Btree*, int); + +int sqlite3BtreeCursor( + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + int(*)(void*,int,const void*,int,const void*), /* Key comparison function */ + void*, /* First argument to compare function */ + BtCursor **ppCursor /* Returned cursor */ +); + +int sqlite3BtreeCloseCursor(BtCursor*); +int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); +int sqlite3BtreeDelete(BtCursor*); +int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias); +int sqlite3BtreeFirst(BtCursor*, int *pRes); +int sqlite3BtreeLast(BtCursor*, int *pRes); +int sqlite3BtreeNext(BtCursor*, int *pRes); +int sqlite3BtreeEof(BtCursor*); +int sqlite3BtreeFlags(BtCursor*); +int sqlite3BtreePrevious(BtCursor*, int *pRes); +int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +sqlite3 *sqlite3BtreeCursorDb(const BtCursor*); +const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); +const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); +int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); + +char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); +struct Pager *sqlite3BtreePager(Btree*); + +int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +void sqlite3BtreeCacheOverflow(BtCursor *); + +#ifdef SQLITE_TEST +int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +void sqlite3BtreeCursorList(Btree*); +int sqlite3BtreePageDump(Btree*, int, int recursive); +#endif + +/* +** If we are not using shared cache, then there is no need to +** use mutexes to access the BtShared structures. So make the +** Enter and Leave procedures no-ops. +*/ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE + void sqlite3BtreeEnter(Btree*); + void sqlite3BtreeLeave(Btree*); + int sqlite3BtreeHoldsMutex(Btree*); + void sqlite3BtreeEnterCursor(BtCursor*); + void sqlite3BtreeLeaveCursor(BtCursor*); + void sqlite3BtreeEnterAll(sqlite3*); + void sqlite3BtreeLeaveAll(sqlite3*); + int sqlite3BtreeHoldsAllMutexes(sqlite3*); + void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*); + void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*); + void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); +#else +# define sqlite3BtreeEnter(X) +# define sqlite3BtreeLeave(X) +# define sqlite3BtreeHoldsMutex(X) 1 +# define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeLeaveCursor(X) +# define sqlite3BtreeEnterAll(X) +# define sqlite3BtreeLeaveAll(X) +# define sqlite3BtreeHoldsAllMutexes(X) 1 +# define sqlite3BtreeMutexArrayEnter(X) +# define sqlite3BtreeMutexArrayLeave(X) +# define sqlite3BtreeMutexArrayInsert(X,Y) +#endif + + +#endif /* _BTREE_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/btreeInt.h b/client/src/thirdparty/sqlite-3.4.2/src/btreeInt.h new file mode 100644 index 0000000..a1e5d42 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/btreeInt.h @@ -0,0 +1,650 @@ +/* +** 2004 April 6 +** +** 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. +** +************************************************************************* +** $Id: btreeInt.h,v 1.15 2007/12/21 04:47:26 danielk1977 Exp $ +** +** This file implements a external (disk-based) database using BTrees. +** For a detailed discussion of BTrees, refer to +** +** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: +** "Sorting And Searching", pages 473-480. Addison-Wesley +** Publishing Company, Reading, Massachusetts. +** +** The basic idea is that each page of the file contains N database +** entries and N+1 pointers to subpages. +** +** ---------------------------------------------------------------- +** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) | +** ---------------------------------------------------------------- +** +** All of the keys on the page that Ptr(0) points to have values less +** than Key(0). All of the keys on page Ptr(1) and its subpages have +** values greater than Key(0) and less than Key(1). All of the keys +** on Ptr(N) and its subpages have values greater than Key(N-1). And +** so forth. +** +** Finding a particular key requires reading O(log(M)) pages from the +** disk where M is the number of entries in the tree. +** +** In this implementation, a single file can hold one or more separate +** BTrees. Each BTree is identified by the index of its root page. The +** key and data for any entry are combined to form the "payload". A +** fixed amount of payload can be carried directly on the database +** page. If the payload is larger than the preset amount then surplus +** bytes are stored on overflow pages. The payload for an entry +** and the preceding pointer are combined to form a "Cell". Each +** page has a small header which contains the Ptr(N) pointer and other +** information such as the size of key and data. +** +** FORMAT DETAILS +** +** The file is divided into pages. The first page is called page 1, +** the second is page 2, and so forth. A page number of zero indicates +** "no such page". The page size can be anything between 512 and 65536. +** Each page can be either a btree page, a freelist page or an overflow +** page. +** +** The first page is always a btree page. The first 100 bytes of the first +** page contain a special header (the "file header") that describes the file. +** The format of the file header is as follows: +** +** OFFSET SIZE DESCRIPTION +** 0 16 Header string: "SQLite format 3\000" +** 16 2 Page size in bytes. +** 18 1 File format write version +** 19 1 File format read version +** 20 1 Bytes of unused space at the end of each page +** 21 1 Max embedded payload fraction +** 22 1 Min embedded payload fraction +** 23 1 Min leaf payload fraction +** 24 4 File change counter +** 28 4 Reserved for future use +** 32 4 First freelist page +** 36 4 Number of freelist pages in the file +** 40 60 15 4-byte meta values passed to higher layers +** +** All of the integer values are big-endian (most significant byte first). +** +** The file change counter is incremented when the database is changed +** This counter allows other processes to know when the file has changed +** and thus when they need to flush their cache. +** +** The max embedded payload fraction is the amount of the total usable +** space in a page that can be consumed by a single cell for standard +** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default +** is to limit the maximum cell size so that at least 4 cells will fit +** on one page. Thus the default max embedded payload fraction is 64. +** +** If the payload for a cell is larger than the max payload, then extra +** payload is spilled to overflow pages. Once an overflow page is allocated, +** as many bytes as possible are moved into the overflow pages without letting +** the cell size drop below the min embedded payload fraction. +** +** The min leaf payload fraction is like the min embedded payload fraction +** except that it applies to leaf nodes in a LEAFDATA tree. The maximum +** payload fraction for a LEAFDATA tree is always 100% (or 255) and it +** not specified in the header. +** +** Each btree pages is divided into three sections: The header, the +** cell pointer array, and the cell content area. Page 1 also has a 100-byte +** file header that occurs before the page header. +** +** |----------------| +** | file header | 100 bytes. Page 1 only. +** |----------------| +** | page header | 8 bytes for leaves. 12 bytes for interior nodes +** |----------------| +** | cell pointer | | 2 bytes per cell. Sorted order. +** | array | | Grows downward +** | | v +** |----------------| +** | unallocated | +** | space | +** |----------------| ^ Grows upwards +** | cell content | | Arbitrary order interspersed with freeblocks. +** | area | | and free space fragments. +** |----------------| +** +** The page headers looks like this: +** +** OFFSET SIZE DESCRIPTION +** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf +** 1 2 byte offset to the first freeblock +** 3 2 number of cells on this page +** 5 2 first byte of the cell content area +** 7 1 number of fragmented free bytes +** 8 4 Right child (the Ptr(N) value). Omitted on leaves. +** +** The flags define the format of this btree page. The leaf flag means that +** this page has no children. The zerodata flag means that this page carries +** only keys and no data. The intkey flag means that the key is a integer +** which is stored in the key size entry of the cell header rather than in +** the payload area. +** +** The cell pointer array begins on the first byte after the page header. +** The cell pointer array contains zero or more 2-byte numbers which are +** offsets from the beginning of the page to the cell content in the cell +** content area. The cell pointers occur in sorted order. The system strives +** to keep free space after the last cell pointer so that new cells can +** be easily added without having to defragment the page. +** +** Cell content is stored at the very end of the page and grows toward the +** beginning of the page. +** +** Unused space within the cell content area is collected into a linked list of +** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset +** to the first freeblock is given in the header. Freeblocks occur in +** increasing order. Because a freeblock must be at least 4 bytes in size, +** any group of 3 or fewer unused bytes in the cell content area cannot +** exist on the freeblock chain. A group of 3 or fewer free bytes is called +** a fragment. The total number of bytes in all fragments is recorded. +** in the page header at offset 7. +** +** SIZE DESCRIPTION +** 2 Byte offset of the next freeblock +** 2 Bytes in this freeblock +** +** Cells are of variable length. Cells are stored in the cell content area at +** the end of the page. Pointers to the cells are in the cell pointer array +** that immediately follows the page header. Cells is not necessarily +** contiguous or in order, but cell pointers are contiguous and in order. +** +** Cell content makes use of variable length integers. A variable +** length integer is 1 to 9 bytes where the lower 7 bits of each +** byte are used. The integer consists of all bytes that have bit 8 set and +** the first byte with bit 8 clear. The most significant byte of the integer +** appears first. A variable-length integer may not be more than 9 bytes long. +** As a special case, all 8 bytes of the 9th byte are used as data. This +** allows a 64-bit integer to be encoded in 9 bytes. +** +** 0x00 becomes 0x00000000 +** 0x7f becomes 0x0000007f +** 0x81 0x00 becomes 0x00000080 +** 0x82 0x00 becomes 0x00000100 +** 0x80 0x7f becomes 0x0000007f +** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 +** +** Variable length integers are used for rowids and to hold the number of +** bytes of key and data in a btree cell. +** +** The content of a cell looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of the left child. Omitted if leaf flag is set. +** var Number of bytes of data. Omitted if the zerodata flag is set. +** var Number of bytes of key. Or the key itself if intkey flag is set. +** * Payload +** 4 First page of the overflow chain. Omitted if no overflow +** +** Overflow pages form a linked list. Each page except the last is completely +** filled with data (pagesize - 4 bytes). The last page can have as little +** as 1 byte of data. +** +** SIZE DESCRIPTION +** 4 Page number of next overflow page +** * Data +** +** Freelist pages come in two subtypes: trunk pages and leaf pages. The +** file header points to the first in a linked list of trunk page. Each trunk +** page points to multiple leaf pages. The content of a leaf page is +** unspecified. A trunk page looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of next trunk page +** 4 Number of leaf pointers on this page +** * zero or more pages numbers of leaves +*/ +#include "sqliteInt.h" +#include "pager.h" +#include "btree.h" +#include "os.h" +#include + +/* Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) ((x+7)&~7) + + +/* The following value is the maximum cell size assuming a maximum page +** size give above. +*/ +#define MX_CELL_SIZE(pBt) (pBt->pageSize-8) + +/* The maximum number of cells on a single page of the database. This +** assumes a minimum cell size of 3 bytes. Such small cells will be +** exceedingly rare, but they are possible. +*/ +#define MX_CELL(pBt) ((pBt->pageSize-8)/3) + +/* Forward declarations */ +typedef struct MemPage MemPage; +typedef struct BtLock BtLock; + +/* +** This is a magic string that appears at the beginning of every +** SQLite database in order to identify the file as a real database. +** +** You can change this value at compile-time by specifying a +** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The +** header must be exactly 16 bytes including the zero-terminator so +** the string itself should be 15 characters long. If you change +** the header, then your custom library will not be able to read +** databases generated by the standard tools and the standard tools +** will not be able to read databases created by your custom library. +*/ +#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ +# define SQLITE_FILE_HEADER "SQLite format 3" +#endif + +/* +** Page type flags. An ORed combination of these flags appear as the +** first byte of on-disk image of every BTree page. +*/ +#define PTF_INTKEY 0x01 +#define PTF_ZERODATA 0x02 +#define PTF_LEAFDATA 0x04 +#define PTF_LEAF 0x08 + +/* +** As each page of the file is loaded into memory, an instance of the following +** structure is appended and initialized to zero. This structure stores +** information about the page that is decoded from the raw file page. +** +** The pParent field points back to the parent page. This allows us to +** walk up the BTree from any leaf to the root. Care must be taken to +** unref() the parent page pointer when this page is no longer referenced. +** The pageDestructor() routine handles that chore. +** +** Access to all fields of this structure is controlled by the mutex +** stored in MemPage.pBt->mutex. +*/ +struct MemPage { + u8 isInit; /* True if previously initialized. MUST BE FIRST! */ + u8 idxShift; /* True if Cell indices have changed */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 intKey; /* True if intkey flag is set */ + u8 leaf; /* True if leaf flag is set */ + u8 zeroData; /* True if table stores keys only */ + u8 leafData; /* True if tables stores data on leaves only */ + u8 hasData; /* True if this page stores data */ + u8 hdrOffset; /* 100 for page 1. 0 otherwise */ + u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ + 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 */ + u16 idxParent; /* Index in parent of this node */ + u16 nFree; /* Number of free bytes on the page */ + u16 nCell; /* Number of cells on this page, local and ovfl */ + struct _OvflCell { /* Cells that will not fit on aData[] */ + u8 *pCell; /* Pointers to the body of the overflow cell */ + u16 idx; /* Insert this cell before idx-th non-overflow cell */ + } aOvfl[5]; + BtShared *pBt; /* Pointer to BtShared that this page is part of */ + u8 *aData; /* Pointer to disk image of the page data */ + DbPage *pDbPage; /* Pager page handle */ + Pgno pgno; /* Page number for this page */ + MemPage *pParent; /* The parent of this page. NULL for root */ +}; + +/* +** The in-memory image of a disk page has the auxiliary information appended +** to the end. EXTRA_SIZE is the number of bytes of space needed to hold +** that extra information. +*/ +#define EXTRA_SIZE sizeof(MemPage) + +/* A Btree handle +** +** A database connection contains a pointer to an instance of +** this object for every database file that it has open. This structure +** is opaque to the database connection. The database connection cannot +** see the internals of this structure and only deals with pointers to +** this structure. +** +** For some database files, the same underlying database cache might be +** shared between multiple connections. In that case, each contection +** has it own pointer to this object. But each instance of this object +** points to the same BtShared object. The database cache and the +** schema associated with the database file are all contained within +** the BtShared object. +** +** All fields in this structure are accessed under sqlite3.mutex. +** The pBt pointer itself may not be changed while there exists cursors +** in the referenced BtShared that point back to this Btree since those +** cursors have to do go through this Btree to find their BtShared and +** they often do so without holding sqlite3.mutex. +*/ +struct Btree { + sqlite3 *db; /* The database connection holding this btree */ + BtShared *pBt; /* Sharable content of this btree */ + u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ + u8 sharable; /* True if we can share pBt with another db */ + u8 locked; /* True if db currently has pBt locked */ + int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ + Btree *pNext; /* List of other sharable Btrees from the same db */ + Btree *pPrev; /* Back pointer of the same list */ +}; + +/* +** Btree.inTrans may take one of the following values. +** +** If the shared-data extension is enabled, there may be multiple users +** of the Btree structure. At most one of these may open a write transaction, +** but any number may have active read transactions. +*/ +#define TRANS_NONE 0 +#define TRANS_READ 1 +#define TRANS_WRITE 2 + +/* +** An instance of this object represents a single database file. +** +** A single database file can be in use as the same time by two +** or more database connections. When two or more connections are +** sharing the same database file, each connection has it own +** private Btree object for the file and each of those Btrees points +** to this one BtShared object. BtShared.nRef is the number of +** connections currently sharing this database file. +** +** Fields in this structure are accessed under the BtShared.mutex +** mutex, except for nRef and pNext which are accessed under the +** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field +** may not be modified once it is initially set as long as nRef>0. +** The pSchema field may be set once under BtShared.mutex and +** thereafter is unchanged as long as nRef>0. +*/ +struct BtShared { + Pager *pPager; /* The page cache */ + sqlite3 *db; /* Database connection currently using this Btree */ + BtCursor *pCursor; /* A list of all open cursors */ + MemPage *pPage1; /* First page of the database */ + u8 inStmt; /* True if we are in a statement subtransaction */ + u8 readOnly; /* True if the underlying file is readonly */ + u8 maxEmbedFrac; /* Maximum payload as % of total page size */ + u8 minEmbedFrac; /* Minimum payload as % of total page size */ + u8 minLeafFrac; /* Minimum leaf payload as % of total page size */ + u8 pageSizeFixed; /* True if the page size can no longer be changed */ +#ifndef SQLITE_OMIT_AUTOVACUUM + u8 autoVacuum; /* True if auto-vacuum is enabled */ + u8 incrVacuum; /* True if incr-vacuum is enabled */ + Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */ +#endif + u16 pageSize; /* Total number of bytes on a page */ + u16 usableSize; /* Number of usable bytes on each page */ + int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ + int minLocal; /* Minimum local payload in non-LEAFDATA tables */ + int maxLeaf; /* Maximum local payload in a LEAFDATA table */ + int minLeaf; /* Minimum local payload in a LEAFDATA table */ + u8 inTransaction; /* Transaction state */ + int nTransaction; /* Number of open transactions (read + write) */ + void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ + void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ + sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */ + BusyHandler busyHdr; /* The busy handler for this btree */ +#ifndef SQLITE_OMIT_SHARED_CACHE + int nRef; /* Number of references to this structure */ + BtShared *pNext; /* Next on a list of sharable BtShared structs */ + BtLock *pLock; /* List of locks held on this shared-btree struct */ + Btree *pExclusive; /* Btree with an EXCLUSIVE lock on the whole db */ +#endif +}; + +/* +** An instance of the following structure is used to hold information +** about a cell. The parseCellPtr() function fills in this structure +** based on information extract from the raw disk page. +*/ +typedef struct CellInfo CellInfo; +struct CellInfo { + u8 *pCell; /* Pointer to the start of cell content */ + i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ + u32 nData; /* Number of bytes of data */ + u32 nPayload; /* Total amount of payload */ + u16 nHeader; /* Size of the cell content header in bytes */ + u16 nLocal; /* Amount of payload held locally */ + u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ + u16 nSize; /* Size of the cell content on the main b-tree page */ +}; + +/* +** A cursor is a pointer to a particular entry within a particular +** b-tree within a database file. +** +** The entry is identified by its MemPage and the index in +** MemPage.aCell[] of the entry. +** +** When a single database file can shared by two more database connections, +** but cursors cannot be shared. Each cursor is associated with a +** particular database connection identified BtCursor.pBtree.db. +** +** Fields in this structure are accessed under the BtShared.mutex +** found at self->pBt->mutex. +*/ +struct BtCursor { + Btree *pBtree; /* The Btree to which this cursor belongs */ + BtShared *pBt; /* The BtShared this cursor points to */ + BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ + int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ + void *pArg; /* First arg to xCompare() */ + Pgno pgnoRoot; /* The root page of this tree */ + MemPage *pPage; /* Page that contains the entry */ + int idx; /* Index of the entry in pPage->aCell[] */ + CellInfo info; /* A parse of the cell we are pointing at */ + u8 wrFlag; /* True if writable */ + u8 eState; /* One of the CURSOR_XXX constants (see below) */ + void *pKey; /* Saved key that was cursor's last known position */ + i64 nKey; /* Size of pKey, or last integer key */ + int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */ +#ifndef SQLITE_OMIT_INCRBLOB + u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ + Pgno *aOverflow; /* Cache of overflow page locations */ +#endif +}; + +/* +** Potential values for BtCursor.eState. +** +** CURSOR_VALID: +** Cursor points to a valid entry. getPayload() etc. may be called. +** +** CURSOR_INVALID: +** Cursor does not point to a valid entry. This can happen (for example) +** because the table is empty or because BtreeCursorFirst() has not been +** called. +** +** CURSOR_REQUIRESEEK: +** The table that this cursor was opened on still exists, but has been +** modified since the cursor was last used. The cursor position is saved +** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in +** this state, restoreOrClearCursorPosition() can be called to attempt to +** seek the cursor to the saved position. +** +** CURSOR_FAULT: +** A unrecoverable error (an I/O error or a malloc failure) has occurred +** on a different connection that shares the BtShared cache with this +** cursor. The error has left the cache in an inconsistent state. +** Do nothing else with this cursor. Any attempt to use the cursor +** should return the error code stored in BtCursor.skip +*/ +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 +#define CURSOR_REQUIRESEEK 2 +#define CURSOR_FAULT 3 + +/* +** The TRACE macro will print high-level status information about the +** btree operation when the global variable sqlite3_btree_trace is +** enabled. +*/ +#if SQLITE_TEST +# define TRACE(X) if( sqlite3_btree_trace ){ printf X; fflush(stdout); } +#else +# define TRACE(X) +#endif + +/* +** Routines to read and write variable-length integers. These used to +** be defined locally, but now we use the varint routines in the util.c +** file. +*/ +#define getVarint sqlite3GetVarint +#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B)) +#define putVarint sqlite3PutVarint + +/* The database page the PENDING_BYTE occupies. This page is never used. +** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They +** should possibly be consolidated (presumably in pager.h). +** +** If disk I/O is omitted (meaning that the database is stored purely +** in memory) then there is no pending byte. +*/ +#ifdef SQLITE_OMIT_DISKIO +# define PENDING_BYTE_PAGE(pBt) 0x7fffffff +#else +# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +#endif + +/* +** A linked list of the following structures is stored at BtShared.pLock. +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor +** is opened on the table with root page BtShared.iTable. Locks are removed +** from this list when a transaction is committed or rolled back, or when +** a btree handle is closed. +*/ +struct BtLock { + Btree *pBtree; /* Btree handle holding this lock */ + Pgno iTable; /* Root page of table */ + u8 eLock; /* READ_LOCK or WRITE_LOCK */ + BtLock *pNext; /* Next in BtShared.pLock list */ +}; + +/* Candidate values for BtLock.eLock */ +#define READ_LOCK 1 +#define WRITE_LOCK 2 + +/* +** These macros define the location of the pointer-map entry for a +** database page. The first argument to each is the number of usable +** bytes on each page of the database (often 1024). The second is the +** page number to look up in the pointer map. +** +** PTRMAP_PAGENO returns the database page number of the pointer-map +** page that stores the required pointer. PTRMAP_PTROFFSET returns +** the offset of the requested map entry. +** +** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page, +** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be +** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements +** this test. +*/ +#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) +#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1)) +#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) + +/* +** The pointer map is a lookup table that identifies the parent page for +** each child page in the database file. The parent page is the page that +** contains a pointer to the child. Every page in the database contains +** 0 or 1 parent pages. (In this context 'database page' refers +** to any page that is not part of the pointer map itself.) Each pointer map +** entry consists of a single byte 'type' and a 4 byte parent page number. +** The PTRMAP_XXX identifiers below are the valid types. +** +** The purpose of the pointer map is to facility moving pages from one +** position in the file to another as part of autovacuum. When a page +** is moved, the pointer in its parent must be updated to point to the +** new location. The pointer map is used to locate the parent page quickly. +** +** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not +** used in this case. +** +** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number +** is not used in this case. +** +** PTRMAP_OVERFLOW1: The database page is the first page in a list of +** overflow pages. The page number identifies the page that +** contains the cell with a pointer to this overflow page. +** +** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of +** overflow pages. The page-number identifies the previous +** page in the overflow page list. +** +** PTRMAP_BTREE: The database page is a non-root btree page. The page number +** identifies the parent page in the btree. +*/ +#define PTRMAP_ROOTPAGE 1 +#define PTRMAP_FREEPAGE 2 +#define PTRMAP_OVERFLOW1 3 +#define PTRMAP_OVERFLOW2 4 +#define PTRMAP_BTREE 5 + +/* A bunch of assert() statements to check the transaction state variables +** of handle p (type Btree*) are internally consistent. +*/ +#define btreeIntegrity(p) \ + assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ + assert( p->pBt->inTransaction>=p->inTrans ); + + +/* +** The ISAUTOVACUUM macro is used within balance_nonroot() to determine +** if the database supports auto-vacuum or not. Because it is used +** within an expression that is an argument to another macro +** (sqliteMallocRaw), it is not possible to use conditional compilation. +** So, this macro is defined instead. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +#define ISAUTOVACUUM (pBt->autoVacuum) +#else +#define ISAUTOVACUUM 0 +#endif + + +/* +** This structure is passed around through all the sanity checking routines +** in order to keep track of some global state information. +*/ +typedef struct IntegrityCk IntegrityCk; +struct IntegrityCk { + BtShared *pBt; /* The tree being checked out */ + Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ + int nPage; /* Number of pages in the database */ + int *anRef; /* Number of times each page is referenced */ + int mxErr; /* Stop accumulating errors when this reaches zero */ + char *zErrMsg; /* An error message. NULL if no errors seen. */ + int nErr; /* Number of messages written to zErrMsg so far */ +}; + +/* +** Read or write a two- and four-byte big-endian integer values. +*/ +#define get2byte(x) ((x)[0]<<8 | (x)[1]) +#define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v)) +#define get4byte sqlite3Get4byte +#define put4byte sqlite3Put4byte + +/* +** Internal routines that should be accessed by the btree layer only. +*/ +int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int); +int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent); +void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*); +void sqlite3BtreeParseCell(MemPage*, int, CellInfo*); +#ifdef SQLITE_TEST +u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell); +#endif +int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur); +void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur); +void sqlite3BtreeReleaseTempCursor(BtCursor *pCur); +int sqlite3BtreeIsRootPage(MemPage *pPage); +void sqlite3BtreeMoveToParent(BtCursor *pCur); diff --git a/client/src/thirdparty/sqlite-3.4.2/src/build.c b/client/src/thirdparty/sqlite-3.4.2/src/build.c new file mode 100644 index 0000000..9c7d82c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/build.c @@ -0,0 +1,3467 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains C code routines that are called by the SQLite parser +** when syntax rules are reduced. The routines in this file handle the +** following kinds of SQL syntax: +** +** CREATE TABLE +** DROP TABLE +** CREATE INDEX +** DROP INDEX +** creating ID lists +** BEGIN TRANSACTION +** COMMIT +** ROLLBACK +** +** $Id: build.c,v 1.472 2008/01/31 13:35:49 drh Exp $ +*/ +#include "sqliteInt.h" +#include + +/* +** This routine is called when a new SQL statement is beginning to +** be parsed. Initialize the pParse structure as needed. +*/ +void sqlite3BeginParse(Parse *pParse, int explainFlag){ + pParse->explain = explainFlag; + pParse->nVar = 0; +} + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** The TableLock structure is only used by the sqlite3TableLock() and +** codeTableLocks() functions. +*/ +struct TableLock { + int iDb; /* The database containing the table to be locked */ + int iTab; /* The root page of the table to be locked */ + u8 isWriteLock; /* True for write lock. False for a read lock */ + const char *zName; /* Name of the table */ +}; + +/* +** Record the fact that we want to lock a table at run-time. +** +** The table to be locked has root page iTab and is found in database iDb. +** A read or a write lock can be taken depending on isWritelock. +** +** This routine just records the fact that the lock is desired. The +** code to make the lock occur is generated by a later call to +** codeTableLocks() which occurs during sqlite3FinishCoding(). +*/ +void sqlite3TableLock( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database containing the table to lock */ + int iTab, /* Root page number of the table to be locked */ + u8 isWriteLock, /* True for a write lock */ + const char *zName /* Name of the table to be locked */ +){ + int i; + int nBytes; + TableLock *p; + + if( iDb<0 ){ + return; + } + + for(i=0; inTableLock; i++){ + p = &pParse->aTableLock[i]; + if( p->iDb==iDb && p->iTab==iTab ){ + p->isWriteLock = (p->isWriteLock || isWriteLock); + return; + } + } + + nBytes = sizeof(TableLock) * (pParse->nTableLock+1); + pParse->aTableLock = + sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes); + if( pParse->aTableLock ){ + p = &pParse->aTableLock[pParse->nTableLock++]; + p->iDb = iDb; + p->iTab = iTab; + p->isWriteLock = isWriteLock; + p->zName = zName; + }else{ + pParse->nTableLock = 0; + pParse->db->mallocFailed = 1; + } +} + +/* +** Code an OP_TableLock instruction for each table locked by the +** statement (configured by calls to sqlite3TableLock()). +*/ +static void codeTableLocks(Parse *pParse){ + int i; + Vdbe *pVdbe; + + if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ + return; + } + + for(i=0; inTableLock; i++){ + TableLock *p = &pParse->aTableLock[i]; + int p1 = p->iDb; + if( p->isWriteLock ){ + p1 = -1*(p1+1); + } + sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, 0, p->zName, P4_STATIC); + } +} +#else + #define codeTableLocks(x) +#endif + +/* +** This routine is called after a single SQL statement has been +** parsed and a VDBE program to execute that statement has been +** prepared. This routine puts the finishing touches on the +** VDBE program and resets the pParse structure for the next +** parse. +** +** Note that if an error occurred, it might be the case that +** no VDBE code was generated. +*/ +void sqlite3FinishCoding(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + db = pParse->db; + if( db->mallocFailed ) return; + if( pParse->nested ) return; + if( pParse->nErr ) return; + if( !pParse->pVdbe ){ + if( pParse->rc==SQLITE_OK && pParse->nErr ){ + pParse->rc = SQLITE_ERROR; + return; + } + } + + /* Begin by generating some termination code at the end of the + ** vdbe program + */ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp0(v, OP_Halt); + + /* The cookie mask contains one bit for each database file open. + ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are + ** set for each database that is used. Generate code to start a + ** transaction on each used database and to verify the schema cookie + ** on each used database. + */ + if( pParse->cookieGoto>0 ){ + u32 mask; + int iDb; + sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); + for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ + if( (mask & pParse->cookieMask)==0 ) continue; + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); + sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pParse->pVirtualLock ){ + char *vtab = (char *)pParse->pVirtualLock->pVtab; + sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); + } +#endif + + /* Once all the cookies have been verified and transactions opened, + ** obtain the required table-locks. This is a no-op unless the + ** shared-cache feature is enabled. + */ + codeTableLocks(pParse); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto); + } + +#ifndef SQLITE_OMIT_TRACE + if( !db->init.busy ){ + /* Change the P4 argument of the first opcode (which will always be + ** an OP_Trace) to be the complete text of the current SQL statement. + */ + VdbeOp *pOp = sqlite3VdbeGetOp(v, 0); + if( pOp && pOp->opcode==OP_Trace ){ + sqlite3VdbeChangeP4(v, 0, pParse->zSql, pParse->zTail-pParse->zSql); + } + } +#endif /* SQLITE_OMIT_TRACE */ + } + + + /* Get the VDBE program ready for execution + */ + if( v && pParse->nErr==0 && !db->mallocFailed ){ +#ifdef SQLITE_DEBUG + FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; + sqlite3VdbeTrace(v, trace); +#endif + sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, + pParse->nTab+3, pParse->explain); + pParse->rc = SQLITE_DONE; + pParse->colNamesSet = 0; + }else if( pParse->rc==SQLITE_OK ){ + pParse->rc = SQLITE_ERROR; + } + pParse->nTab = 0; + pParse->nMem = 0; + pParse->nSet = 0; + pParse->nVar = 0; + pParse->cookieMask = 0; + pParse->cookieGoto = 0; +} + +/* +** Run the parser and code generator recursively in order to generate +** code for the SQL statement given onto the end of the pParse context +** currently under construction. When the parser is run recursively +** this way, the final OP_Halt is not appended and other initialization +** and finalization steps are omitted because those are handling by the +** outermost parser. +** +** Not everything is nestable. This facility is designed to permit +** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use +** care if you decide to try to use this routine for some other purposes. +*/ +void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ + va_list ap; + char *zSql; +# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) + char saveBuf[SAVE_SZ]; + + if( pParse->nErr ) return; + assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ + va_start(ap, zFormat); + zSql = sqlite3VMPrintf(pParse->db, zFormat, ap); + va_end(ap); + if( zSql==0 ){ + pParse->db->mallocFailed = 1; + return; /* A malloc must have failed */ + } + pParse->nested++; + memcpy(saveBuf, &pParse->nVar, SAVE_SZ); + memset(&pParse->nVar, 0, SAVE_SZ); + sqlite3RunParser(pParse, zSql, 0); + sqlite3_free(zSql); + memcpy(&pParse->nVar, saveBuf, SAVE_SZ); + pParse->nested--; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the table and the +** first matching table is returned. (No checking for duplicate table +** names is done.) The search order is TEMP first, then MAIN, then any +** auxiliary databases added using the ATTACH command. +** +** See also sqlite3LocateTable(). +*/ +Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ + Table *p = 0; + int i; + assert( zName!=0 ); + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, strlen(zName)+1); + if( p ) break; + } + return p; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. Also leave an +** error message in pParse->zErrMsg. +** +** The difference between this routine and sqlite3FindTable() is that this +** routine leaves an error message in pParse->zErrMsg where +** sqlite3FindTable() does not. +*/ +Table *sqlite3LocateTable( + Parse *pParse, /* context in which to report errors */ + int isView, /* True if looking for a VIEW rather than a TABLE */ + const char *zName, /* Name of the table we are looking for */ + const char *zDbase /* Name of the database. Might be NULL */ +){ + Table *p; + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return 0; + } + + p = sqlite3FindTable(pParse->db, zName, zDbase); + if( p==0 ){ + const char *zMsg = isView ? "no such view" : "no such table"; + if( zDbase ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName); + } + pParse->checkSchema = 1; + } + return p; +} + +/* +** Locate the in-memory structure that describes +** a particular index given the name of that index +** and the name of the database that contains the index. +** Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the +** table and the first matching index is returned. (No checking +** for duplicate index names is done.) The search order is +** TEMP first, then MAIN, then any auxiliary databases added +** using the ATTACH command. +*/ +Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ + Index *p = 0; + int i; + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + Schema *pSchema = db->aDb[j].pSchema; + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + assert( pSchema || (j==1 && !db->aDb[1].pBt) ); + if( pSchema ){ + p = sqlite3HashFind(&pSchema->idxHash, zName, strlen(zName)+1); + } + if( p ) break; + } + return p; +} + +/* +** Reclaim the memory used by an index +*/ +static void freeIndex(Index *p){ + sqlite3_free(p->zColAff); + sqlite3_free(p); +} + +/* +** Remove the given index from the index hash table, and free +** its memory structures. +** +** The index is removed from the database hash tables but +** it is not unlinked from the Table that it indexes. +** Unlinking from the Table must be done by the calling function. +*/ +static void sqliteDeleteIndex(Index *p){ + Index *pOld; + const char *zName = p->zName; + + pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0); + assert( pOld==0 || pOld==p ); + freeIndex(p); +} + +/* +** For the index called zIdxName which is found in the database iDb, +** unlike that index from its Table then remove the index from +** the index hash table and free all memory structures associated +** with the index. +*/ +void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ + Index *pIndex; + int len; + Hash *pHash = &db->aDb[iDb].pSchema->idxHash; + + len = strlen(zIdxName); + pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0); + if( pIndex ){ + if( pIndex->pTable->pIndex==pIndex ){ + pIndex->pTable->pIndex = pIndex->pNext; + }else{ + Index *p; + for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} + if( p && p->pNext==pIndex ){ + p->pNext = pIndex->pNext; + } + } + freeIndex(pIndex); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Erase all schema information from the in-memory hash tables of +** a single database. This routine is called to reclaim memory +** before the database closes. It is also called during a rollback +** if there were schema changes during the transaction or if a +** schema-cookie mismatch occurs. +** +** If iDb<=0 then reset the internal schema tables for all database +** files. If iDb>=2 then reset the internal schema for only the +** single file indicated. +*/ +void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ + int i, j; + assert( iDb>=0 && iDbnDb ); + + if( iDb==0 ){ + sqlite3BtreeEnterAll(db); + } + for(i=iDb; inDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ + assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt))); + sqlite3SchemaFree(pDb->pSchema); + } + if( iDb>0 ) return; + } + assert( iDb==0 ); + db->flags &= ~SQLITE_InternChanges; + sqlite3BtreeLeaveAll(db); + + /* If one or more of the auxiliary database files has been closed, + ** then remove them from the auxiliary database list. We take the + ** opportunity to do this here since we have just deleted all of the + ** schema hash tables and therefore do not have to make any changes + ** to any of those tables. + */ + for(i=0; inDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); + pDb->pAux = 0; + } + } + for(i=j=2; inDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + sqlite3_free(pDb->zName); + pDb->zName = 0; + continue; + } + if( jaDb[j] = db->aDb[i]; + } + j++; + } + memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); + db->nDb = j; + if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ + memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); + sqlite3_free(db->aDb); + db->aDb = db->aDbStatic; + } +} + +/* +** This routine is called when a commit occurs. +*/ +void sqlite3CommitInternalChanges(sqlite3 *db){ + db->flags &= ~SQLITE_InternChanges; +} + +/* +** Clear the column names from a table or view. +*/ +static void sqliteResetColumnNames(Table *pTable){ + int i; + Column *pCol; + assert( pTable!=0 ); + if( (pCol = pTable->aCol)!=0 ){ + for(i=0; inCol; i++, pCol++){ + sqlite3_free(pCol->zName); + sqlite3ExprDelete(pCol->pDflt); + sqlite3_free(pCol->zType); + sqlite3_free(pCol->zColl); + } + sqlite3_free(pTable->aCol); + } + pTable->aCol = 0; + pTable->nCol = 0; +} + +/* +** Remove the memory data structures associated with the given +** Table. No changes are made to disk by this routine. +** +** This routine just deletes the data structure. It does not unlink +** the table data structure from the hash table. Nor does it remove +** foreign keys from the sqlite.aFKey hash table. But it does destroy +** memory structures of the indices and foreign keys associated with +** the table. +*/ +void sqlite3DeleteTable(Table *pTable){ + Index *pIndex, *pNext; + FKey *pFKey, *pNextFKey; + + if( pTable==0 ) return; + + /* Do not delete the table until the reference count reaches zero. */ + pTable->nRef--; + if( pTable->nRef>0 ){ + return; + } + assert( pTable->nRef==0 ); + + /* Delete all indices associated with this table + */ + for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ + pNext = pIndex->pNext; + assert( pIndex->pSchema==pTable->pSchema ); + sqliteDeleteIndex(pIndex); + } + +#ifndef SQLITE_OMIT_FOREIGN_KEY + /* Delete all foreign keys associated with this table. The keys + ** should have already been unlinked from the pSchema->aFKey hash table + */ + for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ + pNextFKey = pFKey->pNextFrom; + assert( sqlite3HashFind(&pTable->pSchema->aFKey, + pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); + sqlite3_free(pFKey); + } +#endif + + /* Delete the Table structure itself. + */ + sqliteResetColumnNames(pTable); + sqlite3_free(pTable->zName); + sqlite3_free(pTable->zColAff); + sqlite3SelectDelete(pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK + sqlite3ExprDelete(pTable->pCheck); +#endif + sqlite3VtabClear(pTable); + sqlite3_free(pTable); +} + +/* +** Unlink the given table from the hash tables and the delete the +** table structure with all its indices and foreign keys. +*/ +void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ + Table *p; + FKey *pF1, *pF2; + Db *pDb; + + assert( db!=0 ); + assert( iDb>=0 && iDbnDb ); + assert( zTabName && zTabName[0] ); + pDb = &db->aDb[iDb]; + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, strlen(zTabName)+1,0); + if( p ){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ + int nTo = strlen(pF1->zTo) + 1; + pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo); + if( pF2==pF1 ){ + sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo); + }else{ + while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } + if( pF2 ){ + pF2->pNextTo = pF1->pNextTo; + } + } + } +#endif + sqlite3DeleteTable(p); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Given a token, return a string that consists of the text of that +** token with any quotations removed. Space to hold the returned string +** is obtained from sqliteMalloc() and must be freed by the calling +** function. +** +** Tokens are often just pointers into the original SQL text and so +** are not \000 terminated and are not persistent. The returned string +** is \000 terminated and is persistent. +*/ +char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ + char *zName; + if( pName ){ + zName = sqlite3DbStrNDup(db, (char*)pName->z, pName->n); + sqlite3Dequote(zName); + }else{ + zName = 0; + } + return zName; +} + +/* +** Open the sqlite_master table stored in database number iDb for +** writing. The table is opened using cursor 0. +*/ +void sqlite3OpenMasterTable(Parse *p, int iDb){ + Vdbe *v = sqlite3GetVdbe(p); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ +} + +/* +** The token *pName contains the name of a database (either "main" or +** "temp" or the name of an attached db). This routine returns the +** index of the named database in db->aDb[], or -1 if the named db +** does not exist. +*/ +int sqlite3FindDb(sqlite3 *db, Token *pName){ + int i = -1; /* Database number */ + int n; /* Number of characters in the name */ + Db *pDb; /* A database whose name space is being searched */ + char *zName; /* Name we are searching for */ + + zName = sqlite3NameFromToken(db, pName); + if( zName ){ + n = strlen(zName); + for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ + if( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) && + 0==sqlite3StrICmp(pDb->zName, zName) ){ + break; + } + } + sqlite3_free(zName); + } + return i; +} + +/* The table or view or trigger name is passed to this routine via tokens +** pName1 and pName2. If the table name was fully qualified, for example: +** +** CREATE TABLE xxx.yyy (...); +** +** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if +** the table name is not fully qualified, i.e.: +** +** CREATE TABLE yyy(...); +** +** Then pName1 is set to "yyy" and pName2 is "". +** +** This routine sets the *ppUnqual pointer to point at the token (pName1 or +** pName2) that stores the unqualified table name. The index of the +** database "xxx" is returned. +*/ +int sqlite3TwoPartName( + Parse *pParse, /* Parsing and code generating context */ + Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ + Token *pName2, /* The "yyy" in the name "xxx.yyy" */ + Token **pUnqual /* Write the unqualified object name here */ +){ + int iDb; /* Database holding the object */ + sqlite3 *db = pParse->db; + + if( pName2 && pName2->n>0 ){ + assert( !db->init.busy ); + *pUnqual = pName2; + iDb = sqlite3FindDb(db, pName1); + if( iDb<0 ){ + sqlite3ErrorMsg(pParse, "unknown database %T", pName1); + pParse->nErr++; + return -1; + } + }else{ + assert( db->init.iDb==0 || db->init.busy ); + iDb = db->init.iDb; + *pUnqual = pName1; + } + return iDb; +} + +/* +** This routine is used to check if the UTF-8 string zName is a legal +** unqualified name for a new schema object (table, index, view or +** trigger). All names are legal except those that begin with the string +** "sqlite_" (in upper, lower or mixed case). This portion of the namespace +** is reserved for internal use. +*/ +int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +/* +** Begin constructing a new table representation in memory. This is +** the first of several action routines that get called in response +** to a CREATE TABLE statement. In particular, this routine is called +** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp +** flag is true if the table should be stored in the auxiliary database +** file instead of in the main database file. This is normally the case +** when the "TEMP" or "TEMPORARY" keyword occurs in between +** CREATE and TABLE. +** +** The new table record is initialized and put in pParse->pNewTable. +** As more of the CREATE TABLE statement is parsed, additional action +** routines will be called to add more information to this record. +** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine +** is called to complete the construction of the new table record. +*/ +void sqlite3StartTable( + Parse *pParse, /* Parser context */ + Token *pName1, /* First part of the name of the table or view */ + Token *pName2, /* Second part of the name of the table or view */ + int isTemp, /* True if this is a TEMP table */ + int isView, /* True if this is a VIEW */ + int isVirtual, /* True if this is a VIRTUAL table */ + int noErr /* Do nothing if table already exists */ +){ + Table *pTable; + char *zName = 0; /* The name of the new table */ + sqlite3 *db = pParse->db; + Vdbe *v; + int iDb; /* Database number to create the table in */ + Token *pName; /* Unqualified name of the table to create */ + + /* The table or view name to create is passed to this routine via tokens + ** pName1 and pName2. If the table name was fully qualified, for example: + ** + ** CREATE TABLE xxx.yyy (...); + ** + ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if + ** the table name is not fully qualified, i.e.: + ** + ** CREATE TABLE yyy(...); + ** + ** Then pName1 is set to "yyy" and pName2 is "". + ** + ** The call below sets the pName pointer to point at the token (pName1 or + ** pName2) that stores the unqualified table name. The variable iDb is + ** set to the index of the database that the table or view is to be + ** created in. + */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) return; + if( !OMIT_TEMPDB && isTemp && iDb>1 ){ + /* If creating a temp table, the name may not be qualified */ + sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); + return; + } + if( !OMIT_TEMPDB && isTemp ) iDb = 1; + + pParse->sNameToken = *pName; + zName = sqlite3NameFromToken(db, pName); + if( zName==0 ) return; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto begin_table_error; + } + if( db->init.iDb==1 ) isTemp = 1; +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( (isTemp & 1)==isTemp ); + { + int code; + char *zDb = db->aDb[iDb].zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ + goto begin_table_error; + } + if( isView ){ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_VIEW; + }else{ + code = SQLITE_CREATE_VIEW; + } + }else{ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_TABLE; + }else{ + code = SQLITE_CREATE_TABLE; + } + } + if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ + goto begin_table_error; + } + } +#endif + + /* Make sure the new table name does not collide with an existing + ** index or table name in the same database. Issue an error message if + ** it does. The exception is if the statement being parsed was passed + ** to an sqlite3_declare_vtab() call. In that case only the column names + ** and types will be used, so there is no need to test for namespace + ** collisions. + */ + if( !IN_DECLARE_VTAB ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; + } + pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); + if( pTable ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "table %T already exists", pName); + } + goto begin_table_error; + } + if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ + sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); + goto begin_table_error; + } + } + + pTable = sqlite3DbMallocZero(db, sizeof(Table)); + if( pTable==0 ){ + db->mallocFailed = 1; + pParse->rc = SQLITE_NOMEM; + pParse->nErr++; + goto begin_table_error; + } + pTable->zName = zName; + pTable->iPKey = -1; + pTable->pSchema = db->aDb[iDb].pSchema; + pTable->nRef = 1; + if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable); + pParse->pNewTable = pTable; + + /* If this is the magic sqlite_sequence table used by autoincrement, + ** then record a pointer to this table in the main database structure + ** so that INSERT can find the table easily. + */ +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ + pTable->pSchema->pSeqTab = pTable; + } +#endif + + /* Begin generating the code that will insert the table record into + ** the SQLITE_MASTER table. Note in particular that we must go ahead + ** and allocate the record number for the table entry now. Before any + ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause + ** indices to be created and the table record must come before the + ** indices. Hence, the record number for the table must be allocated + ** now. + */ + if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ + int j1; + int fileFormat; + int reg1, reg2, reg3; + sqlite3BeginWriteOperation(pParse, 0, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtual ){ + sqlite3VdbeAddOp0(v, OP_VBegin); + } +#endif + + /* If the file format and encoding in the database have not been set, + ** set them now. + */ + reg1 = pParse->regRowid = ++pParse->nMem; + reg2 = pParse->regRoot = ++pParse->nMem; + reg3 = ++pParse->nMem; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, 1); /* file_format */ + sqlite3VdbeUsesBtree(v, iDb); + j1 = sqlite3VdbeAddOp1(v, OP_If, reg3); + fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? + 1 : SQLITE_MAX_FILE_FORMAT; + sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, reg3); + sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 4, reg3); + sqlite3VdbeJumpHere(v, j1); + + /* This just creates a place-holder record in the sqlite_master table. + ** The record created does not contain anything yet. It will be replaced + ** by the real entry in code generated at sqlite3EndTable(). + ** + ** The rowid for the new entry is left on the top of the stack. + ** The rowid value is needed by the code that sqlite3EndTable will + ** generate. + */ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) + if( isView || isVirtual ){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2); + }else +#endif + { + sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2); + } + sqlite3OpenMasterTable(pParse, iDb); + sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1); + sqlite3VdbeAddOp2(v, OP_Null, 0, reg3); + sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3VdbeAddOp0(v, OP_Close); + } + + /* Normal (non-error) return. */ + return; + + /* If an error occurs, we jump here */ +begin_table_error: + sqlite3_free(zName); + return; +} + +/* +** This macro is used to compare two strings in a case-insensitive manner. +** It is slightly faster than calling sqlite3StrICmp() directly, but +** produces larger code. +** +** WARNING: This macro is not compatible with the strcmp() family. It +** returns true if the two strings are equal, otherwise false. +*/ +#define STRICMP(x, y) (\ +sqlite3UpperToLower[*(unsigned char *)(x)]== \ +sqlite3UpperToLower[*(unsigned char *)(y)] \ +&& sqlite3StrICmp((x)+1,(y)+1)==0 ) + +/* +** Add a new column to the table currently being constructed. +** +** The parser calls this routine once for each column declaration +** in a CREATE TABLE statement. sqlite3StartTable() gets called +** first to get things going. Then this routine is called for each +** column. +*/ +void sqlite3AddColumn(Parse *pParse, Token *pName){ + Table *p; + int i; + char *z; + Column *pCol; + if( (p = pParse->pNewTable)==0 ) return; + if( p->nCol+1>SQLITE_MAX_COLUMN ){ + sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); + return; + } + z = sqlite3NameFromToken(pParse->db, pName); + if( z==0 ) return; + for(i=0; inCol; i++){ + if( STRICMP(z, p->aCol[i].zName) ){ + sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); + sqlite3_free(z); + return; + } + } + if( (p->nCol & 0x7)==0 ){ + Column *aNew; + aNew = sqlite3DbRealloc(pParse->db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0])); + if( aNew==0 ){ + sqlite3_free(z); + return; + } + p->aCol = aNew; + } + pCol = &p->aCol[p->nCol]; + memset(pCol, 0, sizeof(p->aCol[0])); + pCol->zName = z; + + /* If there is no type specified, columns have the default affinity + ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will + ** be called next to set pCol->affinity correctly. + */ + pCol->affinity = SQLITE_AFF_NONE; + p->nCol++; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. A "NOT NULL" constraint has +** been seen on a column. This routine sets the notNull flag on +** the column currently under construction. +*/ +void sqlite3AddNotNull(Parse *pParse, int onError){ + Table *p; + int i; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + if( i>=0 ) p->aCol[i].notNull = onError; +} + +/* +** Scan the column type name zType (length nType) and return the +** associated affinity type. +** +** This routine does a case-independent search of zType for the +** substrings in the following table. If one of the substrings is +** found, the corresponding affinity is returned. If zType contains +** more than one of the substrings, entries toward the top of +** the table take priority. For example, if zType is 'BLOBINT', +** SQLITE_AFF_INTEGER is returned. +** +** Substring | Affinity +** -------------------------------- +** 'INT' | SQLITE_AFF_INTEGER +** 'CHAR' | SQLITE_AFF_TEXT +** 'CLOB' | SQLITE_AFF_TEXT +** 'TEXT' | SQLITE_AFF_TEXT +** 'BLOB' | SQLITE_AFF_NONE +** 'REAL' | SQLITE_AFF_REAL +** 'FLOA' | SQLITE_AFF_REAL +** 'DOUB' | SQLITE_AFF_REAL +** +** If none of the substrings in the above table are found, +** SQLITE_AFF_NUMERIC is returned. +*/ +char sqlite3AffinityType(const Token *pType){ + u32 h = 0; + char aff = SQLITE_AFF_NUMERIC; + const unsigned char *zIn = pType->z; + const unsigned char *zEnd = &pType->z[pType->n]; + + while( zIn!=zEnd ){ + h = (h<<8) + sqlite3UpperToLower[*zIn]; + zIn++; + if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ + && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ + aff = SQLITE_AFF_NONE; +#ifndef SQLITE_OMIT_FLOATING_POINT + }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; +#endif + }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ + aff = SQLITE_AFF_INTEGER; + break; + } + } + + return aff; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. The pFirst token is the first +** token in the sequence of tokens that describe the type of the +** column currently under construction. pLast is the last token +** in the sequence. Use this information to construct a string +** that contains the typename of the column and store that string +** in zType. +*/ +void sqlite3AddColumnType(Parse *pParse, Token *pType){ + Table *p; + int i; + Column *pCol; + + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + if( i<0 ) return; + pCol = &p->aCol[i]; + sqlite3_free(pCol->zType); + pCol->zType = sqlite3NameFromToken(pParse->db, pType); + pCol->affinity = sqlite3AffinityType(pType); +} + +/* +** The expression is the default value for the most recently added column +** of the table currently under construction. +** +** Default value expressions must be constant. Raise an exception if this +** is not the case. +** +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. +*/ +void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ + Table *p; + Column *pCol; + if( (p = pParse->pNewTable)!=0 ){ + pCol = &(p->aCol[p->nCol-1]); + if( !sqlite3ExprIsConstantOrFunction(pExpr) ){ + sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", + pCol->zName); + }else{ + Expr *pCopy; + sqlite3 *db = pParse->db; + sqlite3ExprDelete(pCol->pDflt); + pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr); + if( pCopy ){ + sqlite3TokenCopy(db, &pCopy->span, &pExpr->span); + } + } + } + sqlite3ExprDelete(pExpr); +} + +/* +** Designate the PRIMARY KEY for the table. pList is a list of names +** of columns that form the primary key. If pList is NULL, then the +** most recently added column of the table is the primary key. +** +** A table can have at most one primary key. If the table already has +** a primary key (and this is the second primary key) then create an +** error. +** +** If the PRIMARY KEY is on a single column whose datatype is INTEGER, +** then we will try to use that column as the rowid. Set the Table.iPKey +** field of the table under construction to be the index of the +** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is +** no INTEGER PRIMARY KEY. +** +** If the key is not an INTEGER PRIMARY KEY, then create a unique +** index for the key. No index is created for INTEGER PRIMARY KEYs. +*/ +void sqlite3AddPrimaryKey( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List of field names to be indexed */ + int onError, /* What to do with a uniqueness conflict */ + int autoInc, /* True if the AUTOINCREMENT keyword is present */ + int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ +){ + Table *pTab = pParse->pNewTable; + char *zType = 0; + int iCol = -1, i; + if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; + if( pTab->hasPrimKey ){ + sqlite3ErrorMsg(pParse, + "table \"%s\" has more than one primary key", pTab->zName); + goto primary_key_exit; + } + pTab->hasPrimKey = 1; + if( pList==0 ){ + iCol = pTab->nCol - 1; + pTab->aCol[iCol].isPrimKey = 1; + }else{ + for(i=0; inExpr; i++){ + for(iCol=0; iColnCol; iCol++){ + if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ + break; + } + } + if( iColnCol ){ + pTab->aCol[iCol].isPrimKey = 1; + } + } + if( pList->nExpr>1 ) iCol = -1; + } + if( iCol>=0 && iColnCol ){ + zType = pTab->aCol[iCol].zType; + } + if( zType && sqlite3StrICmp(zType, "INTEGER")==0 + && sortOrder==SQLITE_SO_ASC ){ + pTab->iPKey = iCol; + pTab->keyConf = onError; + pTab->autoInc = autoInc; + }else if( autoInc ){ +#ifndef SQLITE_OMIT_AUTOINCREMENT + sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " + "INTEGER PRIMARY KEY"); +#endif + }else{ + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); + pList = 0; + } + +primary_key_exit: + sqlite3ExprListDelete(pList); + return; +} + +/* +** Add a new CHECK constraint to the table currently under construction. +*/ +void sqlite3AddCheckConstraint( + Parse *pParse, /* Parsing context */ + Expr *pCheckExpr /* The check expression */ +){ +#ifndef SQLITE_OMIT_CHECK + Table *pTab = pParse->pNewTable; + sqlite3 *db = pParse->db; + if( pTab && !IN_DECLARE_VTAB ){ + /* The CHECK expression must be duplicated so that tokens refer + ** to malloced space and not the (ephemeral) text of the CREATE TABLE + ** statement */ + pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, + sqlite3ExprDup(db, pCheckExpr)); + } +#endif + sqlite3ExprDelete(pCheckExpr); +} + +/* +** Set the collation function of the most recently parsed table column +** to the CollSeq given. +*/ +void sqlite3AddCollateType(Parse *pParse, Token *pToken){ + Table *p; + int i; + char *zColl; /* Dequoted name of collation sequence */ + + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + + zColl = sqlite3NameFromToken(pParse->db, pToken); + if( !zColl ) return; + + if( sqlite3LocateCollSeq(pParse, zColl, -1) ){ + Index *pIdx; + p->aCol[i].zColl = zColl; + + /* If the column is declared as " PRIMARY KEY COLLATE ", + ** then an index may have been created on this column before the + ** collation type was added. Correct this if it is the case. + */ + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nColumn==1 ); + if( pIdx->aiColumn[0]==i ){ + pIdx->azColl[0] = p->aCol[i].zColl; + } + } + }else{ + sqlite3_free(zColl); + } +} + +/* +** This function returns the collation sequence for database native text +** encoding identified by the string zName, length nName. +** +** If the requested collation sequence is not available, or not available +** in the database native encoding, the collation factory is invoked to +** request it. If the collation factory does not supply such a sequence, +** and the sequence is available in another text encoding, then that is +** returned instead. +** +** If no versions of the requested collations sequence are available, or +** another error occurs, NULL is returned and an error message written into +** pParse. +** +** This routine is a wrapper around sqlite3FindCollSeq(). This routine +** invokes the collation factory if the named collation cannot be found +** and generates an error message. +*/ +CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ + sqlite3 *db = pParse->db; + u8 enc = ENC(db); + u8 initbusy = db->init.busy; + CollSeq *pColl; + + pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); + if( !initbusy && (!pColl || !pColl->xCmp) ){ + pColl = sqlite3GetCollSeq(db, pColl, zName, nName); + if( !pColl ){ + if( nName<0 ){ + nName = strlen(zName); + } + sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName); + pColl = 0; + } + } + + return pColl; +} + + +/* +** Generate code that will increment the schema cookie. +** +** The schema cookie is used to determine when the schema for the +** database changes. After each schema change, the cookie value +** changes. When a process first reads the schema it records the +** cookie. Thereafter, whenever it goes to access the database, +** it checks the cookie to make sure the schema has not changed +** since it was last read. +** +** This plan is not completely bullet-proof. It is possible for +** the schema to change multiple times and for the cookie to be +** set back to prior value. But schema changes are infrequent +** and the probability of hitting the same cookie value is only +** 1 chance in 2^32. So we're safe enough. +*/ +void sqlite3ChangeCookie(Parse *pParse, int iDb){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3 *db = pParse->db; + Vdbe *v = pParse->pVdbe; + sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1); + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Measure the number of characters needed to output the given +** identifier. The number returned includes any quotes used +** but does not include the null terminator. +** +** The estimate is conservative. It might be larger that what is +** really needed. +*/ +static int identLength(const char *z){ + int n; + for(n=0; *z; n++, z++){ + if( *z=='"' ){ n++; } + } + return n + 2; +} + +/* +** Write an identifier onto the end of the given string. Add +** quote characters as needed. +*/ +static void identPut(char *z, int *pIdx, char *zSignedIdent){ + unsigned char *zIdent = (unsigned char*)zSignedIdent; + int i, j, needQuote; + i = *pIdx; + for(j=0; zIdent[j]; j++){ + if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break; + } + needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) + || sqlite3KeywordCode(zIdent, j)!=TK_ID; + if( needQuote ) z[i++] = '"'; + for(j=0; zIdent[j]; j++){ + z[i++] = zIdent[j]; + if( zIdent[j]=='"' ) z[i++] = '"'; + } + if( needQuote ) z[i++] = '"'; + z[i] = 0; + *pIdx = i; +} + +/* +** Generate a CREATE TABLE statement appropriate for the given +** table. Memory to hold the text of the statement is obtained +** from sqliteMalloc() and must be freed by the calling function. +*/ +static char *createTableStmt(sqlite3 *db, Table *p, int isTemp){ + int i, k, n; + char *zStmt; + char *zSep, *zSep2, *zEnd, *z; + Column *pCol; + n = 0; + for(pCol = p->aCol, i=0; inCol; i++, pCol++){ + n += identLength(pCol->zName); + z = pCol->zType; + if( z ){ + n += (strlen(z) + 1); + } + } + n += identLength(p->zName); + if( n<50 ){ + zSep = ""; + zSep2 = ","; + zEnd = ")"; + }else{ + zSep = "\n "; + zSep2 = ",\n "; + zEnd = "\n)"; + } + n += 35 + 6*p->nCol; + zStmt = sqlite3_malloc( n ); + if( zStmt==0 ){ + db->mallocFailed = 1; + return 0; + } + sqlite3_snprintf(n, zStmt, + !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE "); + k = strlen(zStmt); + identPut(zStmt, &k, p->zName); + zStmt[k++] = '('; + for(pCol=p->aCol, i=0; inCol; i++, pCol++){ + sqlite3_snprintf(n-k, &zStmt[k], zSep); + k += strlen(&zStmt[k]); + zSep = zSep2; + identPut(zStmt, &k, pCol->zName); + if( (z = pCol->zType)!=0 ){ + zStmt[k++] = ' '; + assert( strlen(z)+k+1<=n ); + sqlite3_snprintf(n-k, &zStmt[k], "%s", z); + k += strlen(z); + } + } + sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd); + return zStmt; +} + +/* +** This routine is called to report the final ")" that terminates +** a CREATE TABLE statement. +** +** The table structure that other action routines have been building +** is added to the internal hash tables, assuming no errors have +** occurred. +** +** An entry for the table is made in the master table on disk, unless +** this is a temporary table or db->init.busy==1. When db->init.busy==1 +** it means we are reading the sqlite_master table because we just +** connected to the database or because the sqlite_master table has +** recently changed, so the entry for this table already exists in +** the sqlite_master table. We do not want to create it again. +** +** If the pSelect argument is not NULL, it means that this routine +** was called to create a table generated from a +** "CREATE TABLE ... AS SELECT ..." statement. The column names of +** the new table will match the result set of the SELECT. +*/ +void sqlite3EndTable( + Parse *pParse, /* Parse context */ + Token *pCons, /* The ',' token after the last column defn. */ + Token *pEnd, /* The final ')' token in the CREATE TABLE */ + Select *pSelect /* Select from a "CREATE ... AS SELECT" */ +){ + Table *p; + sqlite3 *db = pParse->db; + int iDb; + + if( (pEnd==0 && pSelect==0) || pParse->nErr || db->mallocFailed ) { + return; + } + p = pParse->pNewTable; + if( p==0 ) return; + + assert( !db->init.busy || !pSelect ); + + iDb = sqlite3SchemaToIndex(db, p->pSchema); + +#ifndef SQLITE_OMIT_CHECK + /* Resolve names in all CHECK constraint expressions. + */ + if( p->pCheck ){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ + + memset(&sNC, 0, sizeof(sNC)); + memset(&sSrc, 0, sizeof(sSrc)); + sSrc.nSrc = 1; + sSrc.a[0].zName = p->zName; + sSrc.a[0].pTab = p; + sSrc.a[0].iCursor = -1; + sNC.pParse = pParse; + sNC.pSrcList = &sSrc; + sNC.isCheck = 1; + if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){ + return; + } + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ + + /* If the db->init.busy is 1 it means we are reading the SQL off the + ** "sqlite_master" or "sqlite_temp_master" table on the disk. + ** So do not write to the disk again. Extract the root page number + ** for the table from the db->init.newTnum field. (The page number + ** should have been put there by the sqliteOpenCb routine.) + */ + if( db->init.busy ){ + p->tnum = db->init.newTnum; + } + + /* If not initializing, then create a record for the new table + ** in the SQLITE_MASTER table of the database. The record number + ** for the new table entry should already be on the stack. + ** + ** If this is a TEMPORARY table, write the entry into the auxiliary + ** file instead of into the main database file. + */ + if( !db->init.busy ){ + int n; + Vdbe *v; + char *zType; /* "view" or "table" */ + char *zType2; /* "VIEW" or "TABLE" */ + char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + sqlite3VdbeAddOp1(v, OP_Close, 0); + + /* Create the rootpage for the new table and push it onto the stack. + ** A view has no rootpage, so just push a zero onto the stack for + ** views. Initialize zType at the same time. + */ + if( p->pSelect==0 ){ + /* A regular table */ + zType = "table"; + zType2 = "TABLE"; +#ifndef SQLITE_OMIT_VIEW + }else{ + /* A view */ + zType = "view"; + zType2 = "VIEW"; +#endif + } + + /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT + ** statement to populate the new table. The root-page number for the + ** new table is on the top of the vdbe stack. + ** + ** Once the SELECT has been coded by sqlite3Select(), it is in a + ** suitable state to query for the column names and types to be used + ** by the new table. + ** + ** A shared-cache write-lock is not required to write to the new table, + ** as a schema-lock must have already been obtained to create it. Since + ** a schema-lock excludes all other database users, the write-lock would + ** be redundant. + */ + if( pSelect ){ + SelectDest dest; + Table *pSelTab; + + sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb); + sqlite3VdbeChangeP5(v, 1); + pParse->nTab = 2; + sqlite3SelectDestInit(&dest, SRT_Table, 1); + sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); + sqlite3VdbeAddOp1(v, OP_Close, 1); + if( pParse->nErr==0 ){ + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect); + if( pSelTab==0 ) return; + assert( p->aCol==0 ); + p->nCol = pSelTab->nCol; + p->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(pSelTab); + } + } + + /* Compute the complete text of the CREATE statement */ + if( pSelect ){ + zStmt = createTableStmt(db, p, p->pSchema==db->aDb[1].pSchema); + }else{ + n = pEnd->z - pParse->sNameToken.z + 1; + zStmt = sqlite3MPrintf(db, + "CREATE %s %.*s", zType2, n, pParse->sNameToken.z + ); + } + + /* A slot for the record has already been allocated in the + ** SQLITE_MASTER table. We just need to update that slot with all + ** the information we've collected. The rowid for the preallocated + ** slot is the 2nd item on the stack. The top of the stack is the + ** root page for the new table (or a 0 if this is a view). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s " + "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " + "WHERE rowid=#%d", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + zType, + p->zName, + p->zName, + pParse->regRoot, + zStmt, + pParse->regRowid + ); + sqlite3_free(zStmt); + sqlite3ChangeCookie(pParse, iDb); + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* Check to see if we need to create an sqlite_sequence table for + ** keeping track of autoincrement keys. + */ + if( p->autoInc ){ + Db *pDb = &db->aDb[iDb]; + if( pDb->pSchema->pSeqTab==0 ){ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.sqlite_sequence(name,seq)", + pDb->zName + ); + } + } +#endif + + /* Reparse everything to update our internal data structures */ + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, + sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P4_DYNAMIC); + } + + + /* Add the table to the in-memory representation of the database. + */ + if( db->init.busy && pParse->nErr==0 ){ + Table *pOld; + FKey *pFKey; + Schema *pSchema = p->pSchema; + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p); + if( pOld ){ + assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ + db->mallocFailed = 1; + return; + } +#ifndef SQLITE_OMIT_FOREIGN_KEY + for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ + void *data; + int nTo = strlen(pFKey->zTo) + 1; + pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo); + data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey); + if( data==(void *)pFKey ){ + db->mallocFailed = 1; + } + } +#endif + pParse->pNewTable = 0; + db->nTable++; + db->flags |= SQLITE_InternChanges; + +#ifndef SQLITE_OMIT_ALTERTABLE + if( !p->pSelect ){ + const char *zName = (const char *)pParse->sNameToken.z; + int nName; + assert( !pSelect && pCons && pEnd ); + if( pCons->z==0 ){ + pCons = pEnd; + } + nName = (const char *)pCons->z - zName; + p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName); + } +#endif + } +} + +#ifndef SQLITE_OMIT_VIEW +/* +** The parser calls this routine in order to create a new VIEW +*/ +void sqlite3CreateView( + Parse *pParse, /* The parsing context */ + Token *pBegin, /* The CREATE token that begins the statement */ + Token *pName1, /* The token that holds the name of the view */ + Token *pName2, /* The token that holds the name of the view */ + Select *pSelect, /* A SELECT statement that will become the new view */ + int isTemp, /* TRUE for a TEMPORARY view */ + int noErr /* Suppress error messages if VIEW already exists */ +){ + Table *p; + int n; + const unsigned char *z; + Token sEnd; + DbFixer sFix; + Token *pName; + int iDb; + sqlite3 *db = pParse->db; + + if( pParse->nVar>0 ){ + sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); + sqlite3SelectDelete(pSelect); + return; + } + sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); + p = pParse->pNewTable; + if( p==0 || pParse->nErr ){ + sqlite3SelectDelete(pSelect); + return; + } + sqlite3TwoPartName(pParse, pName1, pName2, &pName); + iDb = sqlite3SchemaToIndex(db, p->pSchema); + if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) + && sqlite3FixSelect(&sFix, pSelect) + ){ + sqlite3SelectDelete(pSelect); + return; + } + + /* Make a copy of the entire SELECT statement that defines the view. + ** This will force all the Expr.token.z values to be dynamically + ** allocated rather than point to the input string - which means that + ** they will persist after the current sqlite3_exec() call returns. + */ + p->pSelect = sqlite3SelectDup(db, pSelect); + sqlite3SelectDelete(pSelect); + if( db->mallocFailed ){ + return; + } + if( !db->init.busy ){ + sqlite3ViewGetColumnNames(pParse, p); + } + + /* Locate the end of the CREATE VIEW statement. Make sEnd point to + ** the end. + */ + sEnd = pParse->sLastToken; + if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ + sEnd.z += sEnd.n; + } + sEnd.n = 0; + n = sEnd.z - pBegin->z; + z = (const unsigned char*)pBegin->z; + while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } + sEnd.z = &z[n-1]; + sEnd.n = 1; + + /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ + sqlite3EndTable(pParse, 0, &sEnd, 0); + return; +} +#endif /* SQLITE_OMIT_VIEW */ + +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) +/* +** The Table structure pTable is really a VIEW. Fill in the names of +** the columns of the view in the pTable structure. Return the number +** of errors. If an error is seen leave an error message in pParse->zErrMsg. +*/ +int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ + Table *pSelTab; /* A fake table from which we get the result set */ + Select *pSel; /* Copy of the SELECT that implements the view */ + int nErr = 0; /* Number of errors encountered */ + int n; /* Temporarily holds the number of cursors assigned */ + sqlite3 *db = pParse->db; /* Database connection for malloc errors */ + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + + assert( pTable ); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3VtabCallConnect(pParse, pTable) ){ + return SQLITE_ERROR; + } + if( IsVirtual(pTable) ) return 0; +#endif + +#ifndef SQLITE_OMIT_VIEW + /* A positive nCol means the columns names for this view are + ** already known. + */ + if( pTable->nCol>0 ) return 0; + + /* A negative nCol is a special marker meaning that we are currently + ** trying to compute the column names. If we enter this routine with + ** a negative nCol, it means two or more views form a loop, like this: + ** + ** CREATE VIEW one AS SELECT * FROM two; + ** CREATE VIEW two AS SELECT * FROM one; + ** + ** Actually, this error is caught previously and so the following test + ** should always fail. But we will leave it in place just to be safe. + */ + if( pTable->nCol<0 ){ + sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); + return 1; + } + assert( pTable->nCol>=0 ); + + /* If we get this far, it means we need to compute the table names. + ** Note that the call to sqlite3ResultSetOfSelect() will expand any + ** "*" elements in the results set of the view and will assign cursors + ** to the elements of the FROM clause. But we do not want these changes + ** to be permanent. So the computation is done on a copy of the SELECT + ** statement that defines the view. + */ + assert( pTable->pSelect ); + pSel = sqlite3SelectDup(db, pTable->pSelect); + if( pSel ){ + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; +#ifndef SQLITE_OMIT_AUTHORIZATION + xAuth = db->xAuth; + db->xAuth = 0; + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); + db->xAuth = xAuth; +#else + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); +#endif + pParse->nTab = n; + if( pSelTab ){ + assert( pTable->aCol==0 ); + pTable->nCol = pSelTab->nCol; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(pSelTab); + pTable->pSchema->flags |= DB_UnresetViews; + }else{ + pTable->nCol = 0; + nErr++; + } + sqlite3SelectDelete(pSel); + } else { + nErr++; + } +#endif /* SQLITE_OMIT_VIEW */ + return nErr; +} +#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ + +#ifndef SQLITE_OMIT_VIEW +/* +** Clear the column names from every VIEW in database idx. +*/ +static void sqliteViewResetAll(sqlite3 *db, int idx){ + HashElem *i; + if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; + for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ + Table *pTab = sqliteHashData(i); + if( pTab->pSelect ){ + sqliteResetColumnNames(pTab); + } + } + DbClearProperty(db, idx, DB_UnresetViews); +} +#else +# define sqliteViewResetAll(A,B) +#endif /* SQLITE_OMIT_VIEW */ + +/* +** This function is called by the VDBE to adjust the internal schema +** used by SQLite when the btree layer moves a table root page. The +** root-page of a table or index in database iDb has changed from iFrom +** to iTo. +** +** Ticket #1728: The symbol table might still contain information +** on tables and/or indices that are the process of being deleted. +** If you are unlucky, one of those deleted indices or tables might +** have the same rootpage number as the real table or index that is +** being moved. So we cannot stop searching after the first match +** because the first match might be for one of the deleted indices +** or tables and not the table/index that is actually being moved. +** We must continue looping until all tables and indices with +** rootpage==iFrom have been converted to have a rootpage of iTo +** in order to be certain that we got the right one. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ + HashElem *pElem; + Hash *pHash; + + pHash = &pDb->pSchema->tblHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ + Table *pTab = sqliteHashData(pElem); + if( pTab->tnum==iFrom ){ + pTab->tnum = iTo; + } + } + pHash = &pDb->pSchema->idxHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ + Index *pIdx = sqliteHashData(pElem); + if( pIdx->tnum==iFrom ){ + pIdx->tnum = iTo; + } + } +} +#endif + +/* +** Write code to erase the table with root-page iTable from database iDb. +** Also write code to modify the sqlite_master table and internal schema +** if a root-page of another table is moved by the btree-layer whilst +** erasing iTable (this can happen with an auto-vacuum database). +*/ +static void destroyRootPage(Parse *pParse, int iTable, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* OP_Destroy stores an in integer r1. If this integer + ** is non-zero, then it is the root page number of a table moved to + ** location iTable. The following code modifies the sqlite_master table to + ** reflect this. + ** + ** The "#%d" in the SQL is a special constant that means whatever value + ** is on the top of the stack. See sqlite3RegisterExpr(). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d", + pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1); +#endif + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Write VDBE code to erase table pTab and all associated indices on disk. +** Code to update the sqlite_master tables and internal schema definitions +** in case a root-page belonging to another table is moved by the btree layer +** is also added (this can happen with an auto-vacuum database). +*/ +static void destroyTable(Parse *pParse, Table *pTab){ +#ifdef SQLITE_OMIT_AUTOVACUUM + Index *pIdx; + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, pTab->tnum, iDb); + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + destroyRootPage(pParse, pIdx->tnum, iDb); + } +#else + /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM + ** is not defined), then it is important to call OP_Destroy on the + ** table and index root-pages in order, starting with the numerically + ** largest root-page number. This guarantees that none of the root-pages + ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the + ** following were coded: + ** + ** OP_Destroy 4 0 + ** ... + ** OP_Destroy 5 0 + ** + ** and root page 5 happened to be the largest root-page number in the + ** database, then root page 5 would be moved to page 4 by the + ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit + ** a free-list page. + */ + int iTab = pTab->tnum; + int iDestroyed = 0; + + while( 1 ){ + Index *pIdx; + int iLargest = 0; + + if( iDestroyed==0 || iTabpIndex; pIdx; pIdx=pIdx->pNext){ + int iIdx = pIdx->tnum; + assert( pIdx->pSchema==pTab->pSchema ); + if( (iDestroyed==0 || (iIdxiLargest ){ + iLargest = iIdx; + } + } + if( iLargest==0 ){ + return; + }else{ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, iLargest, iDb); + iDestroyed = iLargest; + } + } +#endif +} + +/* +** This routine is called to do the work of a DROP TABLE statement. +** pName is the name of the table to be dropped. +*/ +void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ + Table *pTab; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + if( pParse->nErr || db->mallocFailed ){ + goto exit_drop_table; + } + assert( pName->nSrc==1 ); + pTab = sqlite3LocateTable(pParse, isView, + pName->a[0].zName, pName->a[0].zDatabase); + + if( pTab==0 ){ + if( noErr ){ + sqlite3ErrorClear(pParse); + } + goto exit_drop_table; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDb>=0 && iDbnDb ); + + /* If pTab is a virtual table, call ViewGetColumnNames() to ensure + ** it is initialized. + */ + if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_drop_table; + } +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code; + const char *zTab = SCHEMA_TABLE(iDb); + const char *zDb = db->aDb[iDb].zName; + const char *zArg2 = 0; + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ + goto exit_drop_table; + } + if( isView ){ + if( !OMIT_TEMPDB && iDb==1 ){ + code = SQLITE_DROP_TEMP_VIEW; + }else{ + code = SQLITE_DROP_VIEW; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( IsVirtual(pTab) ){ + code = SQLITE_DROP_VTABLE; + zArg2 = pTab->pMod->zName; +#endif + }else{ + if( !OMIT_TEMPDB && iDb==1 ){ + code = SQLITE_DROP_TEMP_TABLE; + }else{ + code = SQLITE_DROP_TABLE; + } + } + if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){ + goto exit_drop_table; + } + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ + goto exit_drop_table; + } + } +#endif + if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){ + sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); + goto exit_drop_table; + } + +#ifndef SQLITE_OMIT_VIEW + /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used + ** on a table. + */ + if( isView && pTab->pSelect==0 ){ + sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); + goto exit_drop_table; + } + if( !isView && pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); + goto exit_drop_table; + } +#endif + + /* Generate code to remove the table from the master table + ** on disk. + */ + v = sqlite3GetVdbe(pParse); + if( v ){ + Trigger *pTrigger; + Db *pDb = &db->aDb[iDb]; + sqlite3BeginWriteOperation(pParse, 1, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp0(v, OP_VBegin); + } + } +#endif + + /* Drop all triggers associated with the table being dropped. Code + ** is generated to remove entries from sqlite_master and/or + ** sqlite_temp_master if required. + */ + pTrigger = pTab->pTrigger; + while( pTrigger ){ + assert( pTrigger->pSchema==pTab->pSchema || + pTrigger->pSchema==db->aDb[1].pSchema ); + sqlite3DropTriggerPtr(pParse, pTrigger); + pTrigger = pTrigger->pNext; + } + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* Remove any entries of the sqlite_sequence table associated with + ** the table being dropped. This is done before the table is dropped + ** at the btree level, in case the sqlite_sequence table needs to + ** move as a result of the drop (can happen in auto-vacuum mode). + */ + if( pTab->autoInc ){ + sqlite3NestedParse(pParse, + "DELETE FROM %s.sqlite_sequence WHERE name=%Q", + pDb->zName, pTab->zName + ); + } +#endif + + /* Drop all SQLITE_MASTER table and index entries that refer to the + ** table. The program name loops through the master table and deletes + ** every row that refers to a table of the same name as the one being + ** dropped. Triggers are handled seperately because a trigger can be + ** created in the temp database that refers to a table in another + ** database. + */ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", + pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); + if( !isView && !IsVirtual(pTab) ){ + destroyTable(pParse, pTab); + } + + /* Remove the table entry from SQLite's internal schema and modify + ** the schema cookie. + */ + if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0); + } + sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0); + sqlite3ChangeCookie(pParse, iDb); + } + sqliteViewResetAll(db, iDb); + +exit_drop_table: + sqlite3SrcListDelete(pName); +} + +/* +** This routine is called to create a new foreign key on the table +** currently under construction. pFromCol determines which columns +** in the current table point to the foreign key. If pFromCol==0 then +** connect the key to the last column inserted. pTo is the name of +** the table referred to. pToCol is a list of tables in the other +** pTo table that the foreign key points to. flags contains all +** information about the conflict resolution algorithms specified +** in the ON DELETE, ON UPDATE and ON INSERT clauses. +** +** An FKey structure is created and added to the table currently +** under construction in the pParse->pNewTable field. The new FKey +** is not linked into db->aFKey at this point - that does not happen +** until sqlite3EndTable(). +** +** The foreign key is set for IMMEDIATE processing. A subsequent call +** to sqlite3DeferForeignKey() might change this to DEFERRED. +*/ +void sqlite3CreateForeignKey( + Parse *pParse, /* Parsing context */ + ExprList *pFromCol, /* Columns in this table that point to other table */ + Token *pTo, /* Name of the other table */ + ExprList *pToCol, /* Columns in the other table */ + int flags /* Conflict resolution algorithms. */ +){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + FKey *pFKey = 0; + Table *p = pParse->pNewTable; + int nByte; + int i; + int nCol; + char *z; + + assert( pTo!=0 ); + if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; + if( pFromCol==0 ){ + int iCol = p->nCol-1; + if( iCol<0 ) goto fk_end; + if( pToCol && pToCol->nExpr!=1 ){ + sqlite3ErrorMsg(pParse, "foreign key on %s" + " should reference only one column of table %T", + p->aCol[iCol].zName, pTo); + goto fk_end; + } + nCol = 1; + }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ + sqlite3ErrorMsg(pParse, + "number of columns in foreign key does not match the number of " + "columns in the referenced table"); + goto fk_end; + }else{ + nCol = pFromCol->nExpr; + } + nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; + if( pToCol ){ + for(i=0; inExpr; i++){ + nByte += strlen(pToCol->a[i].zName) + 1; + } + } + pFKey = sqlite3DbMallocZero(pParse->db, nByte ); + if( pFKey==0 ){ + goto fk_end; + } + pFKey->pFrom = p; + pFKey->pNextFrom = p->pFKey; + z = (char*)&pFKey[1]; + pFKey->aCol = (struct sColMap*)z; + z += sizeof(struct sColMap)*nCol; + pFKey->zTo = z; + memcpy(z, pTo->z, pTo->n); + z[pTo->n] = 0; + z += pTo->n+1; + pFKey->pNextTo = 0; + pFKey->nCol = nCol; + if( pFromCol==0 ){ + pFKey->aCol[0].iFrom = p->nCol-1; + }else{ + for(i=0; inCol; j++){ + if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ + pFKey->aCol[i].iFrom = j; + break; + } + } + if( j>=p->nCol ){ + sqlite3ErrorMsg(pParse, + "unknown column \"%s\" in foreign key definition", + pFromCol->a[i].zName); + goto fk_end; + } + } + } + if( pToCol ){ + for(i=0; ia[i].zName); + pFKey->aCol[i].zCol = z; + memcpy(z, pToCol->a[i].zName, n); + z[n] = 0; + z += n+1; + } + } + pFKey->isDeferred = 0; + pFKey->deleteConf = flags & 0xff; + pFKey->updateConf = (flags >> 8 ) & 0xff; + pFKey->insertConf = (flags >> 16 ) & 0xff; + + /* Link the foreign key to the table as the last step. + */ + p->pFKey = pFKey; + pFKey = 0; + +fk_end: + sqlite3_free(pFKey); +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ + sqlite3ExprListDelete(pFromCol); + sqlite3ExprListDelete(pToCol); +} + +/* +** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED +** clause is seen as part of a foreign key definition. The isDeferred +** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. +** The behavior of the most recently created foreign key is adjusted +** accordingly. +*/ +void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + Table *pTab; + FKey *pFKey; + if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; + pFKey->isDeferred = isDeferred; +#endif +} + +/* +** Generate code that will erase and refill index *pIdx. This is +** used to initialize a newly created index or to recompute the +** content of an index in response to a REINDEX command. +** +** if memRootPage is not negative, it means that the index is newly +** created. The register specified by memRootPage contains the +** root page number of the index. If memRootPage is negative, then +** the index already exists and must be cleared before being refilled and +** the root page number of the index is taken from pIndex->tnum. +*/ +static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ + Table *pTab = pIndex->pTable; /* The table that is indexed */ + int iTab = pParse->nTab; /* Btree cursor used for pTab */ + int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */ + int addr1; /* Address of top of loop */ + int tnum; /* Root page of index */ + Vdbe *v; /* Generate code into this virtual machine */ + KeyInfo *pKey; /* KeyInfo for index */ + int regIdxKey; /* Registers containing the index key */ + int regRecord; /* Register holding assemblied index record */ + sqlite3 *db = pParse->db; /* The database connection */ + int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); + +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, + db->aDb[iDb].zName ) ){ + return; + } +#endif + + /* Require a write-lock on the table to perform this operation */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + if( memRootPage>=0 ){ + tnum = memRootPage; + }else{ + tnum = pIndex->tnum; + sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb); + } + pKey = sqlite3IndexKeyinfo(pParse, pIndex); + sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, + (char *)pKey, P4_KEYINFO_HANDOFF); + if( memRootPage>=0 ){ + sqlite3VdbeChangeP5(v, 1); + } + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); + regRecord = sqlite3GetTempReg(pParse); + regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord); + if( pIndex->onError!=OE_None ){ + int j1, j2; + int regRowid; + + regRowid = regIdxKey + pIndex->nColumn; + j1 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdxKey, 0, pIndex->nColumn); + j2 = sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, + 0, regRowid, (char*)regRecord, P4_INT32); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0, + "indexed columns are not unique", P4_STATIC); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeJumpHere(v, j2); + } + sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord); + sqlite3ReleaseTempReg(pParse, regRecord); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp1(v, OP_Close, iTab); + sqlite3VdbeAddOp1(v, OP_Close, iIdx); +} + +/* +** Create a new index for an SQL table. pName1.pName2 is the name of the index +** and pTblList is the name of the table that is to be indexed. Both will +** be NULL for a primary key or an index that is created to satisfy a +** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable +** as the table to be indexed. pParse->pNewTable is a table that is +** currently being constructed by a CREATE TABLE statement. +** +** pList is a list of columns to be indexed. pList will be NULL if this +** is a primary key or unique-constraint on the most recent column added +** to the table currently under construction. +*/ +void sqlite3CreateIndex( + Parse *pParse, /* All information about this parse */ + Token *pName1, /* First part of index name. May be NULL */ + Token *pName2, /* Second part of index name. May be NULL */ + SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ + ExprList *pList, /* A list of columns to be indexed */ + int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + Token *pStart, /* The CREATE token that begins this statement */ + Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ + int sortOrder, /* Sort order of primary key when pList==NULL */ + int ifNotExist /* Omit error if index already exists */ +){ + Table *pTab = 0; /* Table to be indexed */ + Index *pIndex = 0; /* The index to be created */ + char *zName = 0; /* Name of the index */ + int nName; /* Number of characters in zName */ + int i, j; + Token nullId; /* Fake token for an empty ID list */ + DbFixer sFix; /* For assigning database names to pTable */ + int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ + sqlite3 *db = pParse->db; + Db *pDb; /* The specific table containing the indexed database */ + int iDb; /* Index of the database that is being written */ + Token *pName = 0; /* Unqualified name of the index to create */ + struct ExprList_item *pListItem; /* For looping over pList */ + int nCol; + int nExtra = 0; + char *zExtra; + + if( pParse->nErr || db->mallocFailed || IN_DECLARE_VTAB ){ + goto exit_create_index; + } + + /* + ** Find the table that is to be indexed. Return early if not found. + */ + if( pTblName!=0 ){ + + /* Use the two-part index name to determine the database + ** to search for the table. 'Fix' the table name to this db + ** before looking up the table. + */ + assert( pName1 && pName2 ); + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) goto exit_create_index; + +#ifndef SQLITE_OMIT_TEMPDB + /* If the index name was unqualified, check if the the table + ** is a temp table. If so, set the database to 1. Do not do this + ** if initialising a database schema. + */ + if( !db->init.busy ){ + pTab = sqlite3SrcListLookup(pParse, pTblName); + if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ + iDb = 1; + } + } +#endif + + if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && + sqlite3FixSrcList(&sFix, pTblName) + ){ + /* Because the parser constructs pTblName from a single identifier, + ** sqlite3FixSrcList can never fail. */ + assert(0); + } + pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName, + pTblName->a[0].zDatabase); + if( !pTab ) goto exit_create_index; + assert( db->aDb[iDb].pSchema==pTab->pSchema ); + }else{ + assert( pName==0 ); + pTab = pParse->pNewTable; + if( !pTab ) goto exit_create_index; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + } + pDb = &db->aDb[iDb]; + + if( pTab==0 || pParse->nErr ) goto exit_create_index; + if( pTab->readOnly ){ + sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); + goto exit_create_index; + } +#ifndef SQLITE_OMIT_VIEW + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "views may not be indexed"); + goto exit_create_index; + } +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); + goto exit_create_index; + } +#endif + + /* + ** Find the name of the index. Make sure there is not already another + ** index or table with the same name. + ** + ** Exception: If we are reading the names of permanent indices from the + ** sqlite_master table (because some other process changed the schema) and + ** one of the index names collides with the name of a temporary table or + ** index, then we will continue to process this index. + ** + ** If pName==0 it means that we are + ** dealing with a primary key or UNIQUE constraint. We have to invent our + ** own name. + */ + if( pName ){ + zName = sqlite3NameFromToken(db, pName); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; + if( zName==0 ) goto exit_create_index; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_create_index; + } + if( !db->init.busy ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; + if( sqlite3FindTable(db, zName, 0)!=0 ){ + sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); + goto exit_create_index; + } + } + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + } + goto exit_create_index; + } + }else{ + char zBuf[30]; + int n; + Index *pLoop; + for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} + sqlite3_snprintf(sizeof(zBuf),zBuf,"_%d",n); + zName = 0; + sqlite3SetString(&zName, "sqlite_autoindex_", pTab->zName, zBuf, (char*)0); + if( zName==0 ){ + db->mallocFailed = 1; + goto exit_create_index; + } + } + + /* Check for authorization to create an index. + */ +#ifndef SQLITE_OMIT_AUTHORIZATION + { + const char *zDb = pDb->zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ + goto exit_create_index; + } + i = SQLITE_CREATE_INDEX; + if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX; + if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ + goto exit_create_index; + } + } +#endif + + /* If pList==0, it means this routine was called to make a primary + ** key out of the last column added to the table under construction. + ** So create a fake list to simulate this. + */ + if( pList==0 ){ + nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.n = strlen((char*)nullId.z); + pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId); + if( pList==0 ) goto exit_create_index; + pList->a[0].sortOrder = sortOrder; + } + + /* Figure out how many bytes of space are required to store explicitly + ** specified collation sequence names. + */ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + nExtra += (1 + strlen(pExpr->pColl->zName)); + } + } + + /* + ** Allocate the index structure. + */ + nName = strlen(zName); + nCol = pList->nExpr; + pIndex = sqlite3DbMallocZero(db, + sizeof(Index) + /* Index structure */ + sizeof(int)*nCol + /* Index.aiColumn */ + sizeof(int)*(nCol+1) + /* Index.aiRowEst */ + sizeof(char *)*nCol + /* Index.azColl */ + sizeof(u8)*nCol + /* Index.aSortOrder */ + nName + 1 + /* Index.zName */ + nExtra /* Collation sequence names */ + ); + if( db->mallocFailed ){ + goto exit_create_index; + } + pIndex->azColl = (char**)(&pIndex[1]); + pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); + pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]); + pIndex->aSortOrder = (u8 *)(&pIndex->aiRowEst[nCol+1]); + pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); + zExtra = (char *)(&pIndex->zName[nName+1]); + memcpy(pIndex->zName, zName, nName+1); + pIndex->pTable = pTab; + pIndex->nColumn = pList->nExpr; + pIndex->onError = onError; + pIndex->autoIndex = pName==0; + pIndex->pSchema = db->aDb[iDb].pSchema; + + /* Check to see if we should honor DESC requests on index columns + */ + if( pDb->pSchema->file_format>=4 ){ + sortOrderMask = -1; /* Honor DESC */ + }else{ + sortOrderMask = 0; /* Ignore DESC */ + } + + /* Scan the names of the columns of the table to be indexed and + ** load the column indices into the Index structure. Report an error + ** if any column is not found. + */ + for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; + int requestedSortOrder; + char *zColl; /* Collation sequence name */ + + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; + } + if( j>=pTab->nCol ){ + sqlite3ErrorMsg(pParse, "table %s has no column named %s", + pTab->zName, zColName); + goto exit_create_index; + } + /* TODO: Add a test to make sure that the same column is not named + ** more than once within the same index. Only the first instance of + ** the column will ever be used by the optimizer. Note that using the + ** same column more than once cannot be an error because that would + ** break backwards compatibility - it needs to be a warning. + */ + pIndex->aiColumn[i] = j; + if( pListItem->pExpr ){ + assert( pListItem->pExpr->pColl ); + zColl = zExtra; + sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName); + zExtra += (strlen(zColl) + 1); + }else{ + zColl = pTab->aCol[j].zColl; + if( !zColl ){ + zColl = db->pDfltColl->zName; + } + } + if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){ + goto exit_create_index; + } + pIndex->azColl[i] = zColl; + requestedSortOrder = pListItem->sortOrder & sortOrderMask; + pIndex->aSortOrder[i] = requestedSortOrder; + } + sqlite3DefaultRowEst(pIndex); + + if( pTab==pParse->pNewTable ){ + /* This routine has been called to create an automatic index as a + ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or + ** a PRIMARY KEY or UNIQUE clause following the column definitions. + ** i.e. one of: + ** + ** CREATE TABLE t(x PRIMARY KEY, y); + ** CREATE TABLE t(x, y, UNIQUE(x, y)); + ** + ** Either way, check to see if the table already has such an index. If + ** so, don't bother creating this one. This only applies to + ** automatically created indices. Users can do as they wish with + ** explicit indices. + */ + Index *pIdx; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int k; + assert( pIdx->onError!=OE_None ); + assert( pIdx->autoIndex ); + assert( pIndex->onError!=OE_None ); + + if( pIdx->nColumn!=pIndex->nColumn ) continue; + for(k=0; knColumn; k++){ + const char *z1 = pIdx->azColl[k]; + const char *z2 = pIndex->azColl[k]; + if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; + if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break; + if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; + } + if( k==pIdx->nColumn ){ + if( pIdx->onError!=pIndex->onError ){ + /* This constraint creates the same index as a previous + ** constraint specified somewhere in the CREATE TABLE statement. + ** However the ON CONFLICT clauses are different. If both this + ** constraint and the previous equivalent constraint have explicit + ** ON CONFLICT clauses this is an error. Otherwise, use the + ** explicitly specified behaviour for the index. + */ + if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ + sqlite3ErrorMsg(pParse, + "conflicting ON CONFLICT clauses specified", 0); + } + if( pIdx->onError==OE_Default ){ + pIdx->onError = pIndex->onError; + } + } + goto exit_create_index; + } + } + } + + /* Link the new Index structure to its table and to the other + ** in-memory database structures. + */ + if( db->init.busy ){ + Index *p; + p = sqlite3HashInsert(&pIndex->pSchema->idxHash, + pIndex->zName, strlen(pIndex->zName)+1, pIndex); + if( p ){ + assert( p==pIndex ); /* Malloc must have failed */ + db->mallocFailed = 1; + goto exit_create_index; + } + db->flags |= SQLITE_InternChanges; + if( pTblName!=0 ){ + pIndex->tnum = db->init.newTnum; + } + } + + /* If the db->init.busy is 0 then create the index on disk. This + ** involves writing the index into the master table and filling in the + ** index with the current table contents. + ** + ** The db->init.busy is 0 when the user first enters a CREATE INDEX + ** command. db->init.busy is 1 when a database is opened and + ** CREATE INDEX statements are read out of the master table. In + ** the latter case the index already exists on disk, which is why + ** we don't want to recreate it. + ** + ** If pTblName==0 it means this index is generated as a primary key + ** or UNIQUE constraint of a CREATE TABLE statement. Since the table + ** has just been created, it contains no data and the index initialization + ** step can be skipped. + */ + else if( db->init.busy==0 ){ + Vdbe *v; + char *zStmt; + int iMem = ++pParse->nMem; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto exit_create_index; + + + /* Create the rootpage for the index + */ + sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem); + + /* Gather the complete text of the CREATE INDEX statement into + ** the zStmt variable + */ + if( pStart && pEnd ){ + /* A named index with an explicit CREATE INDEX statement */ + zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s", + onError==OE_None ? "" : " UNIQUE", + pEnd->z - pName->z + 1, + pName->z); + }else{ + /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ + /* zStmt = sqlite3MPrintf(""); */ + zStmt = 0; + } + + /* Add an entry in sqlite_master for this index + */ + sqlite3NestedParse(pParse, + "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pIndex->zName, + pTab->zName, + iMem, + zStmt + ); + sqlite3_free(zStmt); + + /* Fill the index with data and reparse the schema. Code an OP_Expire + ** to invalidate all pre-compiled statements. + */ + if( pTblName ){ + sqlite3RefillIndex(pParse, pIndex, iMem); + sqlite3ChangeCookie(pParse, iDb); + sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, + sqlite3MPrintf(db, "name='%q'", pIndex->zName), P4_DYNAMIC); + sqlite3VdbeAddOp1(v, OP_Expire, 0); + } + } + + /* When adding an index to the list of indices for a table, make + ** sure all indices labeled OE_Replace come after all those labeled + ** OE_Ignore. This is necessary for the correct operation of UPDATE + ** and INSERT. + */ + if( db->init.busy || pTblName==0 ){ + if( onError!=OE_Replace || pTab->pIndex==0 + || pTab->pIndex->onError==OE_Replace){ + pIndex->pNext = pTab->pIndex; + pTab->pIndex = pIndex; + }else{ + Index *pOther = pTab->pIndex; + while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ + pOther = pOther->pNext; + } + pIndex->pNext = pOther->pNext; + pOther->pNext = pIndex; + } + pIndex = 0; + } + + /* Clean up before exiting */ +exit_create_index: + if( pIndex ){ + freeIndex(pIndex); + } + sqlite3ExprListDelete(pList); + sqlite3SrcListDelete(pTblName); + sqlite3_free(zName); + return; +} + +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + int j1; + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, 1); + sqlite3VdbeUsesBtree(v, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, minFormat, r2); + j1 = sqlite3VdbeAddOp3(v, OP_Ge, r2, 0, r1); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, r2); + sqlite3VdbeJumpHere(v, j1); + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } +} + +/* +** Fill the Index.aiRowEst[] array with default information - information +** to be used when we have not run the ANALYZE command. +** +** aiRowEst[0] is suppose to contain the number of elements in the index. +** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the +** number of rows in the table that match any particular value of the +** first column of the index. aiRowEst[2] is an estimate of the number +** of rows that match any particular combiniation of the first 2 columns +** of the index. And so forth. It must always be the case that +* +** aiRowEst[N]<=aiRowEst[N-1] +** aiRowEst[N]>=1 +** +** Apart from that, we have little to go on besides intuition as to +** how aiRowEst[] should be initialized. The numbers generated here +** are based on typical values found in actual indices. +*/ +void sqlite3DefaultRowEst(Index *pIdx){ + unsigned *a = pIdx->aiRowEst; + int i; + assert( a!=0 ); + a[0] = 1000000; + for(i=pIdx->nColumn; i>=5; i--){ + a[i] = 5; + } + while( i>=1 ){ + a[i] = 11 - i; + i--; + } + if( pIdx->onError!=OE_None ){ + a[pIdx->nColumn] = 1; + } +} + +/* +** This routine will drop an existing named index. This routine +** implements the DROP INDEX statement. +*/ +void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ + Index *pIndex; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + if( pParse->nErr || db->mallocFailed ){ + goto exit_drop_index; + } + assert( pName->nSrc==1 ); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto exit_drop_index; + } + pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); + if( pIndex==0 ){ + if( !ifExists ){ + sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + } + pParse->checkSchema = 1; + goto exit_drop_index; + } + if( pIndex->autoIndex ){ + sqlite3ErrorMsg(pParse, "index associated with UNIQUE " + "or PRIMARY KEY constraint cannot be dropped", 0); + goto exit_drop_index; + } + iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code = SQLITE_DROP_INDEX; + Table *pTab = pIndex->pTable; + const char *zDb = db->aDb[iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ + goto exit_drop_index; + } + if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; + if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ + goto exit_drop_index; + } + } +#endif + + /* Generate code to remove the index and from the master table */ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE name=%Q", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pIndex->zName + ); + sqlite3ChangeCookie(pParse, iDb); + destroyRootPage(pParse, pIndex->tnum, iDb); + sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0); + } + +exit_drop_index: + sqlite3SrcListDelete(pName); +} + +/* +** pArray is a pointer to an array of objects. Each object in the +** array is szEntry bytes in size. This routine allocates a new +** object on the end of the array. +** +** *pnEntry is the number of entries already in use. *pnAlloc is +** the previously allocated size of the array. initSize is the +** suggested initial array size allocation. +** +** The index of the new entry is returned in *pIdx. +** +** This routine returns a pointer to the array of objects. This +** might be the same as the pArray parameter or it might be a different +** pointer if the array was resized. +*/ +void *sqlite3ArrayAllocate( + sqlite3 *db, /* Connection to notify of malloc failures */ + void *pArray, /* Array of objects. Might be reallocated */ + int szEntry, /* Size of each object in the array */ + int initSize, /* Suggested initial allocation, in elements */ + int *pnEntry, /* Number of objects currently in use */ + int *pnAlloc, /* Current size of the allocation, in elements */ + int *pIdx /* Write the index of a new slot here */ +){ + char *z; + if( *pnEntry >= *pnAlloc ){ + void *pNew; + int newSize; + newSize = (*pnAlloc)*2 + initSize; + pNew = sqlite3DbRealloc(db, pArray, newSize*szEntry); + if( pNew==0 ){ + *pIdx = -1; + return pArray; + } + *pnAlloc = newSize; + pArray = pNew; + } + z = (char*)pArray; + memset(&z[*pnEntry * szEntry], 0, szEntry); + *pIdx = *pnEntry; + ++*pnEntry; + return pArray; +} + +/* +** Append a new element to the given IdList. Create a new IdList if +** need be. +** +** A new IdList is returned, or NULL if malloc() fails. +*/ +IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ + int i; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(IdList) ); + if( pList==0 ) return 0; + pList->nAlloc = 0; + } + pList->a = sqlite3ArrayAllocate( + db, + pList->a, + sizeof(pList->a[0]), + 5, + &pList->nId, + &pList->nAlloc, + &i + ); + if( i<0 ){ + sqlite3IdListDelete(pList); + return 0; + } + pList->a[i].zName = sqlite3NameFromToken(db, pToken); + return pList; +} + +/* +** Delete an IdList. +*/ +void sqlite3IdListDelete(IdList *pList){ + int i; + if( pList==0 ) return; + for(i=0; inId; i++){ + sqlite3_free(pList->a[i].zName); + } + sqlite3_free(pList->a); + sqlite3_free(pList); +} + +/* +** Return the index in pList of the identifier named zId. Return -1 +** if not found. +*/ +int sqlite3IdListIndex(IdList *pList, const char *zName){ + int i; + if( pList==0 ) return -1; + for(i=0; inId; i++){ + if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; + } + return -1; +} + +/* +** Append a new table name to the given SrcList. Create a new SrcList if +** need be. A new entry is created in the SrcList even if pToken is NULL. +** +** A new SrcList is returned, or NULL if malloc() fails. +** +** If pDatabase is not null, it means that the table has an optional +** database name prefix. Like this: "database.table". The pDatabase +** points to the table name and the pTable points to the database name. +** The SrcList.a[].zName field is filled with the table name which might +** come from pTable (if pDatabase is NULL) or from pDatabase. +** SrcList.a[].zDatabase is filled with the database name from pTable, +** or with NULL if no database is specified. +** +** In other words, if call like this: +** +** sqlite3SrcListAppend(D,A,B,0); +** +** Then B is a table name and the database name is unspecified. If called +** like this: +** +** sqlite3SrcListAppend(D,A,B,C); +** +** Then C is the table name and B is the database name. +*/ +SrcList *sqlite3SrcListAppend( + sqlite3 *db, /* Connection to notify of malloc failures */ + SrcList *pList, /* Append to this SrcList. NULL creates a new SrcList */ + Token *pTable, /* Table to append */ + Token *pDatabase /* Database of the table */ +){ + struct SrcList_item *pItem; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(SrcList) ); + if( pList==0 ) return 0; + pList->nAlloc = 1; + } + if( pList->nSrc>=pList->nAlloc ){ + SrcList *pNew; + pList->nAlloc *= 2; + pNew = sqlite3DbRealloc(db, pList, + sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); + if( pNew==0 ){ + sqlite3SrcListDelete(pList); + return 0; + } + pList = pNew; + } + pItem = &pList->a[pList->nSrc]; + memset(pItem, 0, sizeof(pList->a[0])); + if( pDatabase && pDatabase->z==0 ){ + pDatabase = 0; + } + if( pDatabase && pTable ){ + Token *pTemp = pDatabase; + pDatabase = pTable; + pTable = pTemp; + } + pItem->zName = sqlite3NameFromToken(db, pTable); + pItem->zDatabase = sqlite3NameFromToken(db, pDatabase); + pItem->iCursor = -1; + pItem->isPopulated = 0; + pList->nSrc++; + return pList; +} + +/* +** Assign cursors to all tables in a SrcList +*/ +void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ + int i; + struct SrcList_item *pItem; + assert(pList || pParse->db->mallocFailed ); + if( pList ){ + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pItem->iCursor>=0 ) break; + pItem->iCursor = pParse->nTab++; + if( pItem->pSelect ){ + sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + } + } + } +} + +/* +** Delete an entire SrcList including all its substructure. +*/ +void sqlite3SrcListDelete(SrcList *pList){ + int i; + struct SrcList_item *pItem; + if( pList==0 ) return; + for(pItem=pList->a, i=0; inSrc; i++, pItem++){ + sqlite3_free(pItem->zDatabase); + sqlite3_free(pItem->zName); + sqlite3_free(pItem->zAlias); + sqlite3DeleteTable(pItem->pTab); + sqlite3SelectDelete(pItem->pSelect); + sqlite3ExprDelete(pItem->pOn); + sqlite3IdListDelete(pItem->pUsing); + } + sqlite3_free(pList); +} + +/* +** This routine is called by the parser to add a new term to the +** end of a growing FROM clause. The "p" parameter is the part of +** the FROM clause that has already been constructed. "p" is NULL +** if this is the first term of the FROM clause. pTable and pDatabase +** are the name of the table and database named in the FROM clause term. +** pDatabase is NULL if the database name qualifier is missing - the +** usual case. If the term has a alias, then pAlias points to the +** alias token. If the term is a subquery, then pSubquery is the +** SELECT statement that the subquery encodes. The pTable and +** pDatabase parameters are NULL for subqueries. The pOn and pUsing +** parameters are the content of the ON and USING clauses. +** +** Return a new SrcList which encodes is the FROM with the new +** term added. +*/ +SrcList *sqlite3SrcListAppendFromTerm( + Parse *pParse, /* Parsing context */ + SrcList *p, /* The left part of the FROM clause already seen */ + Token *pTable, /* Name of the table to add to the FROM clause */ + Token *pDatabase, /* Name of the database containing pTable */ + Token *pAlias, /* The right-hand side of the AS subexpression */ + Select *pSubquery, /* A subquery used in place of a table name */ + Expr *pOn, /* The ON clause of a join */ + IdList *pUsing /* The USING clause of a join */ +){ + struct SrcList_item *pItem; + sqlite3 *db = pParse->db; + p = sqlite3SrcListAppend(db, p, pTable, pDatabase); + if( p==0 || p->nSrc==0 ){ + sqlite3ExprDelete(pOn); + sqlite3IdListDelete(pUsing); + sqlite3SelectDelete(pSubquery); + return p; + } + pItem = &p->a[p->nSrc-1]; + if( pAlias && pAlias->n ){ + pItem->zAlias = sqlite3NameFromToken(db, pAlias); + } + pItem->pSelect = pSubquery; + pItem->pOn = pOn; + pItem->pUsing = pUsing; + return p; +} + +/* +** When building up a FROM clause in the parser, the join operator +** is initially attached to the left operand. But the code generator +** expects the join operator to be on the right operand. This routine +** Shifts all join operators from left to right for an entire FROM +** clause. +** +** Example: Suppose the join is like this: +** +** A natural cross join B +** +** The operator is "natural cross join". The A and B operands are stored +** in p->a[0] and p->a[1], respectively. The parser initially stores the +** operator with A. This routine shifts that operator over to B. +*/ +void sqlite3SrcListShiftJoinType(SrcList *p){ + if( p && p->a ){ + int i; + for(i=p->nSrc-1; i>0; i--){ + p->a[i].jointype = p->a[i-1].jointype; + } + p->a[0].jointype = 0; + } +} + +/* +** Begin a transaction +*/ +void sqlite3BeginTransaction(Parse *pParse, int type){ + sqlite3 *db; + Vdbe *v; + int i; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( !v ) return; + if( type!=TK_DEFERRED ){ + for(i=0; inDb; i++){ + sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); + sqlite3VdbeUsesBtree(v, i); + } + } + sqlite3VdbeAddOp2(v, OP_AutoCommit, 0, 0); +} + +/* +** Commit a transaction +*/ +void sqlite3CommitTransaction(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 0); + } +} + +/* +** Rollback a transaction +*/ +void sqlite3RollbackTransaction(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || db->mallocFailed ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp2(v, OP_AutoCommit, 1, 1); + } +} + +/* +** Make sure the TEMP database is open and available for use. Return +** the number of errors. Leave any error messages in the pParse structure. +*/ +int sqlite3OpenTempDatabase(Parse *pParse){ + sqlite3 *db = pParse->db; + if( db->aDb[1].pBt==0 && !pParse->explain ){ + int rc; + static const int flags = + SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | + SQLITE_OPEN_DELETEONCLOSE | + SQLITE_OPEN_TEMP_DB; + + rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, flags, + &db->aDb[1].pBt); + if( rc!=SQLITE_OK ){ + sqlite3ErrorMsg(pParse, "unable to open a temporary database " + "file for storing temporary tables"); + pParse->rc = rc; + return 1; + } + assert( (db->flags & SQLITE_InTrans)==0 || db->autoCommit ); + assert( db->aDb[1].pSchema ); + } + return 0; +} + +/* +** Generate VDBE code that will verify the schema cookie and start +** a read-transaction for all named database files. +** +** It is important that all schema cookies be verified and all +** read transactions be started before anything else happens in +** the VDBE program. But this routine can be called after much other +** code has been generated. So here is what we do: +** +** The first time this routine is called, we code an OP_Goto that +** will jump to a subroutine at the end of the program. Then we +** record every database that needs its schema verified in the +** pParse->cookieMask field. Later, after all other code has been +** generated, the subroutine that does the cookie verifications and +** starts the transactions will be coded and the OP_Goto P2 value +** will be made to point to that subroutine. The generation of the +** cookie verification subroutine code happens in sqlite3FinishCoding(). +** +** If iDb<0 then code the OP_Goto only - don't set flag to verify the +** schema on any databases. This can be used to position the OP_Goto +** early in the code, before we know if any database tables will be used. +*/ +void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ + sqlite3 *db; + Vdbe *v; + int mask; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; /* This only happens if there was a prior error */ + db = pParse->db; + if( pParse->cookieGoto==0 ){ + pParse->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; + } + if( iDb>=0 ){ + assert( iDbnDb ); + assert( db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDbcookieMask & mask)==0 ){ + pParse->cookieMask |= mask; + pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; + if( !OMIT_TEMPDB && iDb==1 ){ + sqlite3OpenTempDatabase(pParse); + } + } + } +} + +/* +** Generate VDBE code that prepares for doing an operation that +** might change the database. +** +** This routine starts a new transaction if we are not already within +** a transaction. If we are already within a transaction, then a checkpoint +** is set if the setStatement parameter is true. A checkpoint should +** be set for operations that might fail (due to a constraint) part of +** the way through and which will need to undo some writes without having to +** rollback the whole transaction. For operations where all constraints +** can be checked before any changes are made to the database, it is never +** necessary to undo a write and the checkpoint should not be set. +** +** Only database iDb and the temp database are made writable by this call. +** If iDb==0, then the main and temp databases are made writable. If +** iDb==1 then only the temp database is made writable. If iDb>1 then the +** specified auxiliary database and the temp database are made writable. +*/ +void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3CodeVerifySchema(pParse, iDb); + pParse->writeMask |= 1<nested==0 ){ + sqlite3VdbeAddOp1(v, OP_Statement, iDb); + } + if( (OMIT_TEMPDB || iDb!=1) && pParse->db->aDb[1].pBt!=0 ){ + sqlite3BeginWriteOperation(pParse, setStatement, 1); + } +} + +/* +** Check to see if pIndex uses the collating sequence pColl. Return +** true if it does and false if it does not. +*/ +#ifndef SQLITE_OMIT_REINDEX +static int collationMatch(const char *zColl, Index *pIndex){ + int i; + for(i=0; inColumn; i++){ + const char *z = pIndex->azColl[i]; + if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){ + return 1; + } + } + return 0; +} +#endif + +/* +** Recompute all indices of pTab that use the collating sequence pColl. +** If pColl==0 then recompute all indices of pTab. +*/ +#ifndef SQLITE_OMIT_REINDEX +static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ + Index *pIndex; /* An index associated with pTab */ + + for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ + if( zColl==0 || collationMatch(zColl, pIndex) ){ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); + } + } +} +#endif + +/* +** Recompute all indices of all tables in all databases where the +** indices use the collating sequence pColl. If pColl==0 then recompute +** all indices everywhere. +*/ +#ifndef SQLITE_OMIT_REINDEX +static void reindexDatabases(Parse *pParse, char const *zColl){ + Db *pDb; /* A single database */ + int iDb; /* The database index number */ + sqlite3 *db = pParse->db; /* The database connection */ + HashElem *k; /* For looping over tables in pDb */ + Table *pTab; /* A table in the database */ + + for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ + assert( pDb!=0 ); + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ + pTab = (Table*)sqliteHashData(k); + reindexTable(pParse, pTab, zColl); + } + } +} +#endif + +/* +** Generate code for the REINDEX command. +** +** REINDEX -- 1 +** REINDEX -- 2 +** REINDEX ?.? -- 3 +** REINDEX ?.? -- 4 +** +** Form 1 causes all indices in all attached databases to be rebuilt. +** Form 2 rebuilds all indices in all databases that use the named +** collating function. Forms 3 and 4 rebuild the named index or all +** indices associated with the named table. +*/ +#ifndef SQLITE_OMIT_REINDEX +void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ + CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */ + char *z; /* Name of a table or index */ + const char *zDb; /* Name of the database */ + Table *pTab; /* A table in the database */ + Index *pIndex; /* An index associated with pTab */ + int iDb; /* The database index number */ + sqlite3 *db = pParse->db; /* The database connection */ + Token *pObjName; /* Name of the table or index to be reindexed */ + + /* Read the database schema. If an error occurs, leave an error message + ** and code in pParse and return NULL. */ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + return; + } + + if( pName1==0 || pName1->z==0 ){ + reindexDatabases(pParse, 0); + return; + }else if( pName2==0 || pName2->z==0 ){ + char *zColl; + assert( pName1->z ); + zColl = sqlite3NameFromToken(pParse->db, pName1); + if( !zColl ) return; + pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0); + if( pColl ){ + if( zColl ){ + reindexDatabases(pParse, zColl); + sqlite3_free(zColl); + } + return; + } + sqlite3_free(zColl); + } + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); + if( iDb<0 ) return; + z = sqlite3NameFromToken(db, pObjName); + if( z==0 ) return; + zDb = db->aDb[iDb].zName; + pTab = sqlite3FindTable(db, z, zDb); + if( pTab ){ + reindexTable(pParse, pTab, 0); + sqlite3_free(z); + return; + } + pIndex = sqlite3FindIndex(db, z, zDb); + sqlite3_free(z); + if( pIndex ){ + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); + return; + } + sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); +} +#endif + +/* +** Return a dynamicly allocated KeyInfo structure that can be used +** with OP_OpenRead or OP_OpenWrite to access database index pIdx. +** +** If successful, a pointer to the new structure is returned. In this case +** the caller is responsible for calling sqlite3_free() on the returned +** pointer. If an error occurs (out of memory or missing collation +** sequence), NULL is returned and the state of pParse updated to reflect +** the error. +*/ +KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ + int i; + int nCol = pIdx->nColumn; + int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; + KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(pParse->db, nBytes); + + if( pKey ){ + pKey->db = pParse->db; + pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); + assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); + for(i=0; iazColl[i]; + assert( zColl ); + pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1); + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + pKey->nField = nCol; + } + + if( pParse->nErr ){ + sqlite3_free(pKey); + pKey = 0; + } + return pKey; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/callback.c b/client/src/thirdparty/sqlite-3.4.2/src/callback.c new file mode 100644 index 0000000..009cfd7 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/callback.c @@ -0,0 +1,378 @@ +/* +** 2005 May 23 +** +** 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 functions used to access the internal hash tables +** of user defined functions and collation sequences. +** +** $Id: callback.c,v 1.23 2007/08/29 12:31:26 danielk1977 Exp $ +*/ + +#include "sqliteInt.h" + +/* +** Invoke the 'collation needed' callback to request a collation sequence +** in the database text encoding of name zName, length nName. +** If the collation sequence +*/ +static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ + assert( !db->xCollNeeded || !db->xCollNeeded16 ); + if( nName<0 ) nName = strlen(zName); + if( db->xCollNeeded ){ + char *zExternal = sqlite3DbStrNDup(db, zName, nName); + if( !zExternal ) return; + db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); + sqlite3_free(zExternal); + } +#ifndef SQLITE_OMIT_UTF16 + if( db->xCollNeeded16 ){ + char const *zExternal; + sqlite3_value *pTmp = sqlite3ValueNew(db); + sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); + zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); + if( zExternal ){ + db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); + } + sqlite3ValueFree(pTmp); + } +#endif +} + +/* +** This routine is called if the collation factory fails to deliver a +** collation function in the best encoding but there may be other versions +** of this collation function (for other text encodings) available. Use one +** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if +** possible. +*/ +static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ + CollSeq *pColl2; + char *z = pColl->zName; + int n = strlen(z); + int i; + static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; + for(i=0; i<3; i++){ + pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0); + if( pColl2->xCmp!=0 ){ + memcpy(pColl, pColl2, sizeof(CollSeq)); + pColl->xDel = 0; /* Do not copy the destructor */ + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** This function is responsible for invoking the collation factory callback +** or substituting a collation sequence of a different encoding when the +** requested collation sequence is not available in the database native +** encoding. +** +** If it is not NULL, then pColl must point to the database native encoding +** collation sequence with name zName, length nName. +** +** The return value is either the collation sequence to be used in database +** db for collation type name zName, length nName, or NULL, if no collation +** sequence can be found. +*/ +CollSeq *sqlite3GetCollSeq( + sqlite3* db, + CollSeq *pColl, + const char *zName, + int nName +){ + CollSeq *p; + + p = pColl; + if( !p ){ + p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); + } + if( !p || !p->xCmp ){ + /* No collation sequence of this type for this encoding is registered. + ** Call the collation factory to see if it can supply us with one. + */ + callCollNeeded(db, zName, nName); + p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); + } + if( p && !p->xCmp && synthCollSeq(db, p) ){ + p = 0; + } + assert( !p || p->xCmp ); + return p; +} + +/* +** This routine is called on a collation sequence before it is used to +** check that it is defined. An undefined collation sequence exists when +** a database is loaded that contains references to collation sequences +** that have not been defined by sqlite3_create_collation() etc. +** +** If required, this routine calls the 'collation needed' callback to +** request a definition of the collating sequence. If this doesn't work, +** an equivalent collating sequence that uses a text encoding different +** from the main database is substituted, if one is available. +*/ +int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ + if( pColl ){ + const char *zName = pColl->zName; + CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1); + if( !p ){ + if( pParse->nErr==0 ){ + sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); + } + pParse->nErr++; + return SQLITE_ERROR; + } + assert( p==pColl ); + } + return SQLITE_OK; +} + + + +/* +** Locate and return an entry from the db.aCollSeq hash table. If the entry +** specified by zName and nName is not found and parameter 'create' is +** true, then create a new entry. Otherwise return NULL. +** +** Each pointer stored in the sqlite3.aCollSeq hash table contains an +** array of three CollSeq structures. The first is the collation sequence +** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. +** +** Stored immediately after the three collation sequences is a copy of +** the collation sequence name. A pointer to this string is stored in +** each collation sequence structure. +*/ +static CollSeq *findCollSeqEntry( + sqlite3 *db, + const char *zName, + int nName, + int create +){ + CollSeq *pColl; + if( nName<0 ) nName = strlen(zName); + pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); + + if( 0==pColl && create ){ + pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); + if( pColl ){ + CollSeq *pDel = 0; + pColl[0].zName = (char*)&pColl[3]; + pColl[0].enc = SQLITE_UTF8; + pColl[1].zName = (char*)&pColl[3]; + pColl[1].enc = SQLITE_UTF16LE; + pColl[2].zName = (char*)&pColl[3]; + pColl[2].enc = SQLITE_UTF16BE; + memcpy(pColl[0].zName, zName, nName); + pColl[0].zName[nName] = 0; + pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); + + /* If a malloc() failure occured in sqlite3HashInsert(), it will + ** return the pColl pointer to be deleted (because it wasn't added + ** to the hash table). + */ + assert( pDel==0 || pDel==pColl ); + if( pDel!=0 ){ + db->mallocFailed = 1; + sqlite3_free(pDel); + pColl = 0; + } + } + } + return pColl; +} + +/* +** Parameter zName points to a UTF-8 encoded string nName bytes long. +** Return the CollSeq* pointer for the collation sequence named zName +** for the encoding 'enc' from the database 'db'. +** +** If the entry specified is not found and 'create' is true, then create a +** new entry. Otherwise return NULL. +** +** A separate function sqlite3LocateCollSeq() is a wrapper around +** this routine. sqlite3LocateCollSeq() invokes the collation factory +** if necessary and generates an error message if the collating sequence +** cannot be found. +*/ +CollSeq *sqlite3FindCollSeq( + sqlite3 *db, + u8 enc, + const char *zName, + int nName, + int create +){ + CollSeq *pColl; + if( zName ){ + pColl = findCollSeqEntry(db, zName, nName, create); + }else{ + pColl = db->pDfltColl; + } + assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); + assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); + if( pColl ) pColl += enc-1; + return pColl; +} + +/* +** Locate a user function given a name, a number of arguments and a flag +** indicating whether the function prefers UTF-16 over UTF-8. Return a +** pointer to the FuncDef structure that defines that function, or return +** NULL if the function does not exist. +** +** If the createFlag argument is true, then a new (blank) FuncDef +** structure is created and liked into the "db" structure if a +** no matching function previously existed. When createFlag is true +** and the nArg parameter is -1, then only a function that accepts +** any number of arguments will be returned. +** +** If createFlag is false and nArg is -1, then the first valid +** function found is returned. A function is valid if either xFunc +** or xStep is non-zero. +** +** If createFlag is false, then a function with the required name and +** number of arguments may be returned even if the eTextRep flag does not +** match that requested. +*/ +FuncDef *sqlite3FindFunction( + sqlite3 *db, /* An open database */ + const char *zName, /* Name of the function. Not null-terminated */ + int nName, /* Number of characters in the name */ + int nArg, /* Number of arguments. -1 means any number */ + u8 enc, /* Preferred text encoding */ + int createFlag /* Create new entry if true and does not otherwise exist */ +){ + FuncDef *p; /* Iterator variable */ + FuncDef *pFirst; /* First function with this name */ + FuncDef *pBest = 0; /* Best match found so far */ + int bestmatch = 0; + + + assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); + if( nArg<-1 ) nArg = -1; + + pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); + for(p=pFirst; p; p=p->pNext){ + /* During the search for the best function definition, bestmatch is set + ** as follows to indicate the quality of the match with the definition + ** pointed to by pBest: + ** + ** 0: pBest is NULL. No match has been found. + ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 + ** encoding is requested, or vice versa. + ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is + ** requested, or vice versa. + ** 3: A variable arguments function using the same text encoding. + ** 4: A function with the exact number of arguments requested that + ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. + ** 5: A function with the exact number of arguments requested that + ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. + ** 6: An exact match. + ** + ** A larger value of 'matchqual' indicates a more desirable match. + */ + if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ + int match = 1; /* Quality of this match */ + if( p->nArg==nArg || nArg==-1 ){ + match = 4; + } + if( enc==p->iPrefEnc ){ + match += 2; + } + else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || + (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ + match += 1; + } + + if( match>bestmatch ){ + pBest = p; + bestmatch = match; + } + } + } + + /* If the createFlag parameter is true, and the seach did not reveal an + ** exact match for the name, number of arguments and encoding, then add a + ** new entry to the hash table and return it. + */ + if( createFlag && bestmatch<6 && + (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){ + pBest->nArg = nArg; + pBest->pNext = pFirst; + pBest->iPrefEnc = enc; + memcpy(pBest->zName, zName, nName); + pBest->zName[nName] = 0; + if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ + db->mallocFailed = 1; + sqlite3_free(pBest); + return 0; + } + } + + if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ + return pBest; + } + return 0; +} + +/* +** Free all resources held by the schema structure. The void* argument points +** at a Schema struct. This function does not call sqlite3_free() on the +** pointer itself, it just cleans up subsiduary resources (i.e. the contents +** of the schema hash tables). +*/ +void sqlite3SchemaFree(void *p){ + Hash temp1; + Hash temp2; + HashElem *pElem; + Schema *pSchema = (Schema *)p; + + temp1 = pSchema->tblHash; + temp2 = pSchema->trigHash; + sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashClear(&pSchema->aFKey); + sqlite3HashClear(&pSchema->idxHash); + for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ + sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); + } + sqlite3HashClear(&temp2); + sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0); + for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ + Table *pTab = sqliteHashData(pElem); + sqlite3DeleteTable(pTab); + } + sqlite3HashClear(&temp1); + pSchema->pSeqTab = 0; + pSchema->flags &= ~DB_SchemaLoaded; +} + +/* +** Find and return the schema associated with a BTree. Create +** a new one if necessary. +*/ +Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ + Schema * p; + if( pBt ){ + p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree); + }else{ + p = (Schema *)sqlite3MallocZero(sizeof(Schema)); + } + if( !p ){ + db->mallocFailed = 1; + }else if ( 0==p->file_format ){ + sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1); + p->enc = SQLITE_UTF8; + } + return p; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/complete.c b/client/src/thirdparty/sqlite-3.4.2/src/complete.c new file mode 100644 index 0000000..ae61d8a --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/complete.c @@ -0,0 +1,271 @@ +/* +** 2001 September 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. +** +************************************************************************* +** An tokenizer for SQL +** +** This file contains C code that implements the sqlite3_complete() API. +** This code used to be part of the tokenizer.c source file. But by +** separating it out, the code will be automatically omitted from +** static links that do not use it. +** +** $Id: complete.c,v 1.6 2007/08/27 23:26:59 drh Exp $ +*/ +#include "sqliteInt.h" +#ifndef SQLITE_OMIT_COMPLETE + +/* +** This is defined in tokenize.c. We just have to import the definition. +*/ +#ifndef SQLITE_AMALGAMATION +#ifdef SQLITE_ASCII +extern const char sqlite3IsAsciiIdChar[]; +#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsAsciiIdChar[c-0x20])) +#endif +#ifdef SQLITE_EBCDIC +extern const char sqlite3IsEbcdicIdChar[]; +#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) +#endif +#endif /* SQLITE_AMALGAMATION */ + + +/* +** Token types used by the sqlite3_complete() routine. See the header +** comments on that procedure for additional information. +*/ +#define tkSEMI 0 +#define tkWS 1 +#define tkOTHER 2 +#define tkEXPLAIN 3 +#define tkCREATE 4 +#define tkTEMP 5 +#define tkTRIGGER 6 +#define tkEND 7 + +/* +** Return TRUE if the given SQL string ends in a semicolon. +** +** Special handling is require for CREATE TRIGGER statements. +** Whenever the CREATE TRIGGER keywords are seen, the statement +** must end with ";END;". +** +** This implementation uses a state machine with 7 states: +** +** (0) START At the beginning or end of an SQL statement. This routine +** returns 1 if it ends in the START state and 0 if it ends +** in any other state. +** +** (1) NORMAL We are in the middle of statement which ends with a single +** semicolon. +** +** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of +** a statement. +** +** (3) CREATE The keyword CREATE has been seen at the beginning of a +** statement, possibly preceeded by EXPLAIN and/or followed by +** TEMP or TEMPORARY +** +** (4) TRIGGER We are in the middle of a trigger definition that must be +** ended by a semicolon, the keyword END, and another semicolon. +** +** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at +** the end of a trigger definition. +** +** (6) END We've seen the ";END" of the ";END;" that occurs at the end +** of a trigger difinition. +** +** Transitions between states above are determined by tokens extracted +** from the input. The following tokens are significant: +** +** (0) tkSEMI A semicolon. +** (1) tkWS Whitespace +** (2) tkOTHER Any other SQL token. +** (3) tkEXPLAIN The "explain" keyword. +** (4) tkCREATE The "create" keyword. +** (5) tkTEMP The "temp" or "temporary" keyword. +** (6) tkTRIGGER The "trigger" keyword. +** (7) tkEND The "end" keyword. +** +** Whitespace never causes a state transition and is always ignored. +** +** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed +** to recognize the end of a trigger can be omitted. All we have to do +** is look for a semicolon that is not part of an string or comment. +*/ +int sqlite3_complete(const char *zSql){ + u8 state = 0; /* Current state, using numbers defined in header comment */ + u8 token; /* Value of the next token */ + +#ifndef SQLITE_OMIT_TRIGGER + /* A complex statement machine used to detect the end of a CREATE TRIGGER + ** statement. This is the normal case. + */ + static const u8 trans[7][8] = { + /* Token: */ + /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ + /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, }, + /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, }, + /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, }, + /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, }, + /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, }, + /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, }, + }; +#else + /* If triggers are not suppored by this compile then the statement machine + ** used to detect the end of a statement is much simplier + */ + static const u8 trans[2][3] = { + /* Token: */ + /* State: ** SEMI WS OTHER */ + /* 0 START: */ { 0, 0, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, }, + }; +#endif /* SQLITE_OMIT_TRIGGER */ + + while( *zSql ){ + switch( *zSql ){ + case ';': { /* A semicolon */ + token = tkSEMI; + break; + } + case ' ': + case '\r': + case '\t': + case '\n': + case '\f': { /* White space is ignored */ + token = tkWS; + break; + } + case '/': { /* C-style comments */ + if( zSql[1]!='*' ){ + token = tkOTHER; + break; + } + zSql += 2; + while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } + if( zSql[0]==0 ) return 0; + zSql++; + token = tkWS; + break; + } + case '-': { /* SQL-style comments from "--" to end of line */ + if( zSql[1]!='-' ){ + token = tkOTHER; + break; + } + while( *zSql && *zSql!='\n' ){ zSql++; } + if( *zSql==0 ) return state==0; + token = tkWS; + break; + } + case '[': { /* Microsoft-style identifiers in [...] */ + zSql++; + while( *zSql && *zSql!=']' ){ zSql++; } + if( *zSql==0 ) return 0; + token = tkOTHER; + break; + } + case '`': /* Grave-accent quoted symbols used by MySQL */ + case '"': /* single- and double-quoted strings */ + case '\'': { + int c = *zSql; + zSql++; + while( *zSql && *zSql!=c ){ zSql++; } + if( *zSql==0 ) return 0; + token = tkOTHER; + break; + } + default: { + int c; + if( IdChar((u8)*zSql) ){ + /* Keywords and unquoted identifiers */ + int nId; + for(nId=1; IdChar(zSql[nId]); nId++){} +#ifdef SQLITE_OMIT_TRIGGER + token = tkOTHER; +#else + switch( *zSql ){ + case 'c': case 'C': { + if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ + token = tkCREATE; + }else{ + token = tkOTHER; + } + break; + } + case 't': case 'T': { + if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){ + token = tkTRIGGER; + }else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){ + token = tkTEMP; + }else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){ + token = tkTEMP; + }else{ + token = tkOTHER; + } + break; + } + case 'e': case 'E': { + if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ + token = tkEND; + }else +#ifndef SQLITE_OMIT_EXPLAIN + if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ + token = tkEXPLAIN; + }else +#endif + { + token = tkOTHER; + } + break; + } + default: { + token = tkOTHER; + break; + } + } +#endif /* SQLITE_OMIT_TRIGGER */ + zSql += nId-1; + }else{ + /* Operators and special symbols */ + token = tkOTHER; + } + break; + } + } + state = trans[state][token]; + zSql++; + } + return state==0; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** This routine is the same as the sqlite3_complete() routine described +** above, except that the parameter is required to be UTF-16 encoded, not +** UTF-8. +*/ +int sqlite3_complete16(const void *zSql){ + sqlite3_value *pVal; + char const *zSql8; + int rc = SQLITE_NOMEM; + + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); + if( zSql8 ){ + rc = sqlite3_complete(zSql8); + } + sqlite3ValueFree(pVal); + return sqlite3ApiExit(0, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ +#endif /* SQLITE_OMIT_COMPLETE */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/date.c b/client/src/thirdparty/sqlite-3.4.2/src/date.c new file mode 100644 index 0000000..07ba2f2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/date.c @@ -0,0 +1,1038 @@ +/* +** 2003 October 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. +** +************************************************************************* +** This file contains the C functions that implement date and time +** functions for SQLite. +** +** There is only one exported symbol in this file - the function +** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. +** All other code has file scope. +** +** $Id: date.c,v 1.75 2008/01/17 22:27:54 drh Exp $ +** +** SQLite processes all times and dates as Julian Day numbers. The +** dates and times are stored as the number of days since noon +** in Greenwich on November 24, 4714 B.C. according to the Gregorian +** calendar system. +** +** 1970-01-01 00:00:00 is JD 2440587.5 +** 2000-01-01 00:00:00 is JD 2451544.5 +** +** This implemention requires years to be expressed as a 4-digit number +** which means that only dates between 0000-01-01 and 9999-12-31 can +** be represented, even though julian day numbers allow a much wider +** range of dates. +** +** The Gregorian calendar system is used for all dates and times, +** even those that predate the Gregorian calendar. Historians usually +** use the Julian calendar for dates prior to 1582-10-15 and for some +** dates afterwards, depending on locale. Beware of this difference. +** +** The conversion algorithms are implemented based on descriptions +** in the following text: +** +** Jean Meeus +** Astronomical Algorithms, 2nd Edition, 1998 +** ISBM 0-943396-61-1 +** Willmann-Bell, Inc +** Richmond, Virginia (USA) +*/ +#include "sqliteInt.h" +#include +#include +#include +#include + +#ifndef SQLITE_OMIT_DATETIME_FUNCS + +/* +** A structure for holding a single date and time. +*/ +typedef struct DateTime DateTime; +struct DateTime { + double rJD; /* The julian day number */ + int Y, M, D; /* Year, month, and day */ + int h, m; /* Hour and minutes */ + int tz; /* Timezone offset in minutes */ + double s; /* Seconds */ + char validYMD; /* True if Y,M,D are valid */ + char validHMS; /* True if h,m,s are valid */ + char validJD; /* True if rJD is valid */ + char validTZ; /* True if tz is valid */ +}; + + +/* +** Convert zDate into one or more integers. Additional arguments +** come in groups of 5 as follows: +** +** N number of digits in the integer +** min minimum allowed value of the integer +** max maximum allowed value of the integer +** nextC first character after the integer +** pVal where to write the integers value. +** +** Conversions continue until one with nextC==0 is encountered. +** The function returns the number of successful conversions. +*/ +static int getDigits(const char *zDate, ...){ + va_list ap; + int val; + int N; + int min; + int max; + int nextC; + int *pVal; + int cnt = 0; + va_start(ap, zDate); + do{ + N = va_arg(ap, int); + min = va_arg(ap, int); + max = va_arg(ap, int); + nextC = va_arg(ap, int); + pVal = va_arg(ap, int*); + val = 0; + while( N-- ){ + if( !isdigit(*(u8*)zDate) ){ + goto end_getDigits; + } + val = val*10 + *zDate - '0'; + zDate++; + } + if( valmax || (nextC!=0 && nextC!=*zDate) ){ + goto end_getDigits; + } + *pVal = val; + zDate++; + cnt++; + }while( nextC ); +end_getDigits: + va_end(ap); + return cnt; +} + +/* +** Read text from z[] and convert into a floating point number. Return +** the number of digits converted. +*/ +#define getValue sqlite3AtoF + +/* +** Parse a timezone extension on the end of a date-time. +** The extension is of the form: +** +** (+/-)HH:MM +** +** If the parse is successful, write the number of minutes +** of change in *pnMin and return 0. If a parser error occurs, +** return 0. +** +** A missing specifier is not considered an error. +*/ +static int parseTimezone(const char *zDate, DateTime *p){ + int sgn = 0; + int nHr, nMn; + while( isspace(*(u8*)zDate) ){ zDate++; } + p->tz = 0; + if( *zDate=='-' ){ + sgn = -1; + }else if( *zDate=='+' ){ + sgn = +1; + }else{ + return *zDate!=0; + } + zDate++; + if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){ + return 1; + } + zDate += 5; + p->tz = sgn*(nMn + nHr*60); + while( isspace(*(u8*)zDate) ){ zDate++; } + return *zDate!=0; +} + +/* +** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. +** The HH, MM, and SS must each be exactly 2 digits. The +** fractional seconds FFFF can be one or more digits. +** +** Return 1 if there is a parsing error and 0 on success. +*/ +static int parseHhMmSs(const char *zDate, DateTime *p){ + int h, m, s; + double ms = 0.0; + if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){ + return 1; + } + zDate += 5; + if( *zDate==':' ){ + zDate++; + if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){ + return 1; + } + zDate += 2; + if( *zDate=='.' && isdigit((u8)zDate[1]) ){ + double rScale = 1.0; + zDate++; + while( isdigit(*(u8*)zDate) ){ + ms = ms*10.0 + *zDate - '0'; + rScale *= 10.0; + zDate++; + } + ms /= rScale; + } + }else{ + s = 0; + } + p->validJD = 0; + p->validHMS = 1; + p->h = h; + p->m = m; + p->s = s + ms; + if( parseTimezone(zDate, p) ) return 1; + p->validTZ = p->tz!=0; + return 0; +} + +/* +** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume +** that the YYYY-MM-DD is according to the Gregorian calendar. +** +** Reference: Meeus page 61 +*/ +static void computeJD(DateTime *p){ + int Y, M, D, A, B, X1, X2; + + if( p->validJD ) return; + if( p->validYMD ){ + Y = p->Y; + M = p->M; + D = p->D; + }else{ + Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ + M = 1; + D = 1; + } + if( M<=2 ){ + Y--; + M += 12; + } + A = Y/100; + B = 2 - A + (A/4); + X1 = 365.25*(Y+4716); + X2 = 30.6001*(M+1); + p->rJD = X1 + X2 + D + B - 1524.5; + p->validJD = 1; + if( p->validHMS ){ + p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; + if( p->validTZ ){ + p->rJD -= p->tz*60/86400.0; + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; + } + } +} + +/* +** Parse dates of the form +** +** YYYY-MM-DD HH:MM:SS.FFF +** YYYY-MM-DD HH:MM:SS +** YYYY-MM-DD HH:MM +** YYYY-MM-DD +** +** Write the result into the DateTime structure and return 0 +** on success and 1 if the input string is not a well-formed +** date. +*/ +static int parseYyyyMmDd(const char *zDate, DateTime *p){ + int Y, M, D, neg; + + if( zDate[0]=='-' ){ + zDate++; + neg = 1; + }else{ + neg = 0; + } + if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ + return 1; + } + zDate += 10; + while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; } + if( parseHhMmSs(zDate, p)==0 ){ + /* We got the time */ + }else if( *zDate==0 ){ + p->validHMS = 0; + }else{ + return 1; + } + p->validJD = 0; + p->validYMD = 1; + p->Y = neg ? -Y : Y; + p->M = M; + p->D = D; + if( p->validTZ ){ + computeJD(p); + } + return 0; +} + +/* +** Attempt to parse the given string into a Julian Day Number. Return +** the number of errors. +** +** The following are acceptable forms for the input string: +** +** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM +** DDDD.DD +** now +** +** In the first form, the +/-HH:MM is always optional. The fractional +** seconds extension (the ".FFF") is optional. The seconds portion +** (":SS.FFF") is option. The year and date can be omitted as long +** as there is a time string. The time string can be omitted as long +** as there is a year and date. +*/ +static int parseDateOrTime( + sqlite3_context *context, + const char *zDate, + DateTime *p +){ + memset(p, 0, sizeof(*p)); + if( parseYyyyMmDd(zDate,p)==0 ){ + return 0; + }else if( parseHhMmSs(zDate, p)==0 ){ + return 0; + }else if( sqlite3StrICmp(zDate,"now")==0){ + double r; + sqlite3OsCurrentTime((sqlite3_vfs *)sqlite3_user_data(context), &r); + p->rJD = r; + p->validJD = 1; + return 0; + }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ + getValue(zDate, &p->rJD); + p->validJD = 1; + return 0; + } + return 1; +} + +/* +** Compute the Year, Month, and Day from the julian day number. +*/ +static void computeYMD(DateTime *p){ + int Z, A, B, C, D, E, X1; + if( p->validYMD ) return; + if( !p->validJD ){ + p->Y = 2000; + p->M = 1; + p->D = 1; + }else{ + Z = p->rJD + 0.5; + A = (Z - 1867216.25)/36524.25; + A = Z + 1 + A - (A/4); + B = A + 1524; + C = (B - 122.1)/365.25; + D = 365.25*C; + E = (B-D)/30.6001; + X1 = 30.6001*E; + p->D = B - D - X1; + p->M = E<14 ? E-1 : E-13; + p->Y = p->M>2 ? C - 4716 : C - 4715; + } + p->validYMD = 1; +} + +/* +** Compute the Hour, Minute, and Seconds from the julian day number. +*/ +static void computeHMS(DateTime *p){ + int Z, s; + if( p->validHMS ) return; + computeJD(p); + Z = p->rJD + 0.5; + s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5; + p->s = 0.001*s; + s = p->s; + p->s -= s; + p->h = s/3600; + s -= p->h*3600; + p->m = s/60; + p->s += s - p->m*60; + p->validHMS = 1; +} + +/* +** Compute both YMD and HMS +*/ +static void computeYMD_HMS(DateTime *p){ + computeYMD(p); + computeHMS(p); +} + +/* +** Clear the YMD and HMS and the TZ +*/ +static void clearYMD_HMS_TZ(DateTime *p){ + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; +} + +/* +** Compute the difference (in days) between localtime and UTC (a.k.a. GMT) +** for the time value p where p is in UTC. +*/ +static double localtimeOffset(DateTime *p){ + DateTime x, y; + time_t t; + x = *p; + computeYMD_HMS(&x); + if( x.Y<1971 || x.Y>=2038 ){ + x.Y = 2000; + x.M = 1; + x.D = 1; + x.h = 0; + x.m = 0; + x.s = 0.0; + } else { + int s = x.s + 0.5; + x.s = s; + } + x.tz = 0; + x.validJD = 0; + computeJD(&x); + t = (x.rJD-2440587.5)*86400.0 + 0.5; +#ifdef HAVE_LOCALTIME_R + { + struct tm sLocal; + localtime_r(&t, &sLocal); + y.Y = sLocal.tm_year + 1900; + y.M = sLocal.tm_mon + 1; + y.D = sLocal.tm_mday; + y.h = sLocal.tm_hour; + y.m = sLocal.tm_min; + y.s = sLocal.tm_sec; + } +#else + { + struct tm *pTm; + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + pTm = localtime(&t); + y.Y = pTm->tm_year + 1900; + y.M = pTm->tm_mon + 1; + y.D = pTm->tm_mday; + y.h = pTm->tm_hour; + y.m = pTm->tm_min; + y.s = pTm->tm_sec; + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + } +#endif + y.validYMD = 1; + y.validHMS = 1; + y.validJD = 0; + y.validTZ = 0; + computeJD(&y); + return y.rJD - x.rJD; +} + +/* +** Process a modifier to a date-time stamp. The modifiers are +** as follows: +** +** NNN days +** NNN hours +** NNN minutes +** NNN.NNNN seconds +** NNN months +** NNN years +** start of month +** start of year +** start of week +** start of day +** weekday N +** unixepoch +** localtime +** utc +** +** Return 0 on success and 1 if there is any kind of error. +*/ +static int parseModifier(const char *zMod, DateTime *p){ + int rc = 1; + int n; + double r; + char *z, zBuf[30]; + z = zBuf; + for(n=0; nrJD += localtimeOffset(p); + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } + case 'u': { + /* + ** unixepoch + ** + ** Treat the current value of p->rJD as the number of + ** seconds since 1970. Convert to a real julian day number. + */ + if( strcmp(z, "unixepoch")==0 && p->validJD ){ + p->rJD = p->rJD/86400.0 + 2440587.5; + clearYMD_HMS_TZ(p); + rc = 0; + }else if( strcmp(z, "utc")==0 ){ + double c1; + computeJD(p); + c1 = localtimeOffset(p); + p->rJD -= c1; + clearYMD_HMS_TZ(p); + p->rJD += c1 - localtimeOffset(p); + rc = 0; + } + break; + } + case 'w': { + /* + ** weekday N + ** + ** Move the date to the same time on the next occurrence of + ** weekday N where 0==Sunday, 1==Monday, and so forth. If the + ** date is already on the appropriate weekday, this is a no-op. + */ + if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 + && (n=r)==r && n>=0 && r<7 ){ + int Z; + computeYMD_HMS(p); + p->validTZ = 0; + p->validJD = 0; + computeJD(p); + Z = p->rJD + 1.5; + Z %= 7; + if( Z>n ) Z -= 7; + p->rJD += n - Z; + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } + case 's': { + /* + ** start of TTTTT + ** + ** Move the date backwards to the beginning of the current day, + ** or month or year. + */ + if( strncmp(z, "start of ", 9)!=0 ) break; + z += 9; + computeYMD(p); + p->validHMS = 1; + p->h = p->m = 0; + p->s = 0.0; + p->validTZ = 0; + p->validJD = 0; + if( strcmp(z,"month")==0 ){ + p->D = 1; + rc = 0; + }else if( strcmp(z,"year")==0 ){ + computeYMD(p); + p->M = 1; + p->D = 1; + rc = 0; + }else if( strcmp(z,"day")==0 ){ + rc = 0; + } + break; + } + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + n = getValue(z, &r); + assert( n>=1 ); + if( z[n]==':' ){ + /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the + ** specified number of hours, minutes, seconds, and fractional seconds + ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be + ** omitted. + */ + const char *z2 = z; + DateTime tx; + int day; + if( !isdigit(*(u8*)z2) ) z2++; + memset(&tx, 0, sizeof(tx)); + if( parseHhMmSs(z2, &tx) ) break; + computeJD(&tx); + tx.rJD -= 0.5; + day = (int)tx.rJD; + tx.rJD -= day; + if( z[0]=='-' ) tx.rJD = -tx.rJD; + computeJD(p); + clearYMD_HMS_TZ(p); + p->rJD += tx.rJD; + rc = 0; + break; + } + z += n; + while( isspace(*(u8*)z) ) z++; + n = strlen(z); + if( n>10 || n<3 ) break; + if( z[n-1]=='s' ){ z[n-1] = 0; n--; } + computeJD(p); + rc = 0; + if( n==3 && strcmp(z,"day")==0 ){ + p->rJD += r; + }else if( n==4 && strcmp(z,"hour")==0 ){ + p->rJD += r/24.0; + }else if( n==6 && strcmp(z,"minute")==0 ){ + p->rJD += r/(24.0*60.0); + }else if( n==6 && strcmp(z,"second")==0 ){ + p->rJD += r/(24.0*60.0*60.0); + }else if( n==5 && strcmp(z,"month")==0 ){ + int x, y; + computeYMD_HMS(p); + p->M += r; + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + p->validJD = 0; + computeJD(p); + y = r; + if( y!=r ){ + p->rJD += (r - y)*30.0; + } + }else if( n==4 && strcmp(z,"year")==0 ){ + computeYMD_HMS(p); + p->Y += r; + p->validJD = 0; + computeJD(p); + }else{ + rc = 1; + } + clearYMD_HMS_TZ(p); + break; + } + default: { + break; + } + } + return rc; +} + +/* +** Process time function arguments. argv[0] is a date-time stamp. +** argv[1] and following are modifiers. Parse them all and write +** the resulting time into the DateTime structure p. Return 0 +** on success and 1 if there are any errors. +** +** If there are zero parameters (if even argv[0] is undefined) +** then assume a default value of "now" for argv[0]. +*/ +static int isDate( + sqlite3_context *context, + int argc, + sqlite3_value **argv, + DateTime *p +){ + int i; + const unsigned char *z; + static const unsigned char zDflt[] = "now"; + if( argc==0 ){ + z = zDflt; + }else{ + z = sqlite3_value_text(argv[0]); + } + if( !z || parseDateOrTime(context, (char*)z, p) ){ + return 1; + } + for(i=1; iSQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + }else{ + z = sqlite3_malloc( n ); + if( z==0 ){ + sqlite3_result_error_nomem(context); + return; + } + } + computeJD(&x); + computeYMD_HMS(&x); + for(i=j=0; zFmt[i]; i++){ + if( zFmt[i]!='%' ){ + z[j++] = zFmt[i]; + }else{ + i++; + switch( zFmt[i] ){ + case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break; + case 'f': { + double s = x.s; + if( s>59.999 ) s = 59.999; + sqlite3_snprintf(7, &z[j],"%06.3f", s); + j += strlen(&z[j]); + break; + } + case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break; + case 'W': /* Fall thru */ + case 'j': { + int nDay; /* Number of days since 1st day of year */ + DateTime y = x; + y.validJD = 0; + y.M = 1; + y.D = 1; + computeJD(&y); + nDay = x.rJD - y.rJD + 0.5; + if( zFmt[i]=='W' ){ + int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ + wd = ((int)(x.rJD+0.5)) % 7; + sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7); + j += 2; + }else{ + sqlite3_snprintf(4, &z[j],"%03d",nDay+1); + j += 3; + } + break; + } + case 'J': { + sqlite3_snprintf(20, &z[j],"%.16g",x.rJD); + j+=strlen(&z[j]); + break; + } + case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break; + case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break; + case 's': { + sqlite3_snprintf(30,&z[j],"%d", + (int)((x.rJD-2440587.5)*86400.0 + 0.5)); + j += strlen(&z[j]); + break; + } + case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break; + case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break; + case 'Y': sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=strlen(&z[j]);break; + default: z[j++] = '%'; break; + } + } + } + z[j] = 0; + sqlite3_result_text(context, z, -1, + z==zBuf ? SQLITE_TRANSIENT : sqlite3_free); +} + +/* +** current_time() +** +** This function returns the same value as time('now'). +*/ +static void ctimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + timeFunc(context, 0, 0); +} + +/* +** current_date() +** +** This function returns the same value as date('now'). +*/ +static void cdateFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + dateFunc(context, 0, 0); +} + +/* +** current_timestamp() +** +** This function returns the same value as datetime('now'). +*/ +static void ctimestampFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + datetimeFunc(context, 0, 0); +} +#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ + +#ifdef SQLITE_OMIT_DATETIME_FUNCS +/* +** If the library is compiled to omit the full-scale date and time +** handling (to get a smaller binary), the following minimal version +** of the functions current_time(), current_date() and current_timestamp() +** are included instead. This is to support column declarations that +** include "DEFAULT CURRENT_TIME" etc. +** +** This function uses the C-library functions time(), gmtime() +** and strftime(). The format string to pass to strftime() is supplied +** as the user-data for the function. +*/ +static void currentTimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + time_t t; + char *zFormat = (char *)sqlite3_user_data(context); + char zBuf[20]; + + time(&t); +#ifdef SQLITE_TEST + { + extern int sqlite3_current_time; /* See os_XXX.c */ + if( sqlite3_current_time ){ + t = sqlite3_current_time; + } + } +#endif + +#ifdef HAVE_GMTIME_R + { + struct tm sNow; + gmtime_r(&t, &sNow); + strftime(zBuf, 20, zFormat, &sNow); + } +#else + { + struct tm *pTm; + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + pTm = gmtime(&t); + strftime(zBuf, 20, zFormat, pTm); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + } +#endif + + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +#endif + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +void sqlite3RegisterDateTimeFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_DATETIME_FUNCS + static const struct { + char *zName; + int nArg; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFuncs[] = { + { "julianday", -1, juliandayFunc }, + { "date", -1, dateFunc }, + { "time", -1, timeFunc }, + { "datetime", -1, datetimeFunc }, + { "strftime", -1, strftimeFunc }, + { "current_time", 0, ctimeFunc }, + { "current_timestamp", 0, ctimestampFunc }, + { "current_date", 0, cdateFunc }, + }; + int i; + + for(i=0; ipVfs), aFuncs[i].xFunc, 0, 0); + } +#else + static const struct { + char *zName; + char *zFormat; + } aFuncs[] = { + { "current_time", "%H:%M:%S" }, + { "current_date", "%Y-%m-%d" }, + { "current_timestamp", "%Y-%m-%d %H:%M:%S" } + }; + int i; + + for(i=0; izErrMsg and return NULL. If all tables +** are found, return a pointer to the last table. +*/ +Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ + Table *pTab = 0; + int i; + struct SrcList_item *pItem; + for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){ + pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); + sqlite3DeleteTable(pItem->pTab); + pItem->pTab = pTab; + if( pTab ){ + pTab->nRef++; + } + } + return pTab; +} + +/* +** Check to make sure the given table is writable. If it is not +** writable, generate an error message and return 1. If it is +** writable return 0; +*/ +int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ + if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 + && pParse->nested==0) +#ifndef SQLITE_OMIT_VIRTUALTABLE + || (pTab->pMod && pTab->pMod->pModule->xUpdate==0) +#endif + ){ + sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); + return 1; + } +#ifndef SQLITE_OMIT_VIEW + if( !viewOk && pTab->pSelect ){ + sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); + return 1; + } +#endif + return 0; +} + +/* +** Generate code that will open a table for reading. +*/ +void sqlite3OpenTable( + Parse *p, /* Generate code into this VDBE */ + int iCur, /* The cursor number of the table */ + int iDb, /* The database index in sqlite3.aDb[] */ + Table *pTab, /* The table to be opened */ + int opcode /* OP_OpenRead or OP_OpenWrite */ +){ + Vdbe *v; + if( IsVirtual(pTab) ) return; + v = sqlite3GetVdbe(p); + assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); + sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); + sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); + VdbeComment((v, "%s", pTab->zName)); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, iCur, pTab->nCol); +} + + +/* +** Generate code for a DELETE FROM statement. +** +** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; +** \________/ \________________/ +** pTabList pWhere +*/ +void sqlite3DeleteFrom( + Parse *pParse, /* The parser context */ + SrcList *pTabList, /* The table from which we should delete things */ + Expr *pWhere /* The WHERE clause. May be null */ +){ + Vdbe *v; /* The virtual database engine */ + Table *pTab; /* The table from which records will be deleted */ + const char *zDb; /* Name of database holding pTab */ + int end, addr = 0; /* A couple addresses of generated code */ + int i; /* Loop counter */ + WhereInfo *pWInfo; /* Information about the WHERE clause */ + Index *pIdx; /* For looping over indices of the table */ + int iCur; /* VDBE Cursor number for pTab */ + sqlite3 *db; /* Main database structure */ + AuthContext sContext; /* Authorization context */ + int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */ + NameContext sNC; /* Name context to resolve expressions in */ + int iDb; /* Database number */ + int memCnt = 0; /* Memory cell used for change counting */ + +#ifndef SQLITE_OMIT_TRIGGER + int isView; /* True if attempting to delete from a view */ + int triggers_exist = 0; /* True if any triggers exist */ +#endif + int iBeginAfterTrigger; /* Address of after trigger program */ + int iEndAfterTrigger; /* Exit of after trigger program */ + int iBeginBeforeTrigger; /* Address of before trigger program */ + int iEndBeforeTrigger; /* Exit of before trigger program */ + u32 old_col_mask = 0; /* Mask of OLD.* columns in use */ + + sContext.pParse = 0; + db = pParse->db; + if( pParse->nErr || db->mallocFailed ){ + goto delete_from_cleanup; + } + assert( pTabList->nSrc==1 ); + + /* Locate the table which we want to delete. This table has to be + ** put in an SrcList structure because some of the subroutines we + ** will be calling are designed to work with multiple tables and expect + ** an SrcList* parameter instead of just a Table* parameter. + */ + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ) goto delete_from_cleanup; + + /* Figure out if we have any triggers and if the table being + ** deleted from is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); + isView = pTab->pSelect!=0; +#else +# define triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ + goto delete_from_cleanup; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + zDb = db->aDb[iDb].zName; + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ + goto delete_from_cleanup; + } + + /* If pTab is really a view, make sure it has been initialized. + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto delete_from_cleanup; + } + + /* Allocate a cursor used to store the old.* data for a trigger. + */ + if( triggers_exist ){ + oldIdx = pParse->nTab++; + } + + /* Resolve the column names in the WHERE clause. + */ + assert( pTabList->nSrc==1 ); + iCur = pTabList->a[0].iCursor = pParse->nTab++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + pParse->nTab++; + } + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + if( sqlite3ExprResolveNames(&sNC, pWhere) ){ + goto delete_from_cleanup; + } + + /* Start the view context + */ + if( isView ){ + sqlite3AuthContextPush(pParse, &sContext, pTab->zName); + } + + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + goto delete_from_cleanup; + } + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); + sqlite3BeginWriteOperation(pParse, triggers_exist, iDb); + + if( triggers_exist ){ + int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default); + int iGoto = sqlite3VdbeAddOp0(v, OP_Goto); + addr = sqlite3VdbeMakeLabel(v); + + iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v); + (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab, + -1, oldIdx, orconf, addr, &old_col_mask, 0); + iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto); + + iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v); + (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1, + oldIdx, orconf, addr, &old_col_mask, 0); + iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto); + + sqlite3VdbeJumpHere(v, iGoto); + } + + /* If we are trying to delete from a view, realize that view into + ** a ephemeral table. + */ + if( isView ){ + SelectDest dest; + Select *pView; + + pView = sqlite3SelectDup(db, pTab->pSelect); + sqlite3SelectMask(pParse, pView, old_col_mask); + sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); + sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0); + sqlite3SelectDelete(pView); + } + + /* Initialize the counter of the number of rows deleted, if + ** we are counting rows. + */ + if( db->flags & SQLITE_CountRows ){ + memCnt = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt); + } + + /* Special case: A DELETE without a WHERE clause deletes everything. + ** It is easier just to erase the whole table. Note, however, that + ** this means that the row change count will be incorrect. + */ + if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){ + if( db->flags & SQLITE_CountRows ){ + /* If counting rows deleted, just count the total number of + ** entries in the table. */ + int addr2; + if( !isView ){ + sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead); + } + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2); + addr2 = sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + sqlite3VdbeAddOp2(v, OP_Next, iCur, addr2); + sqlite3VdbeAddOp1(v, OP_Close, iCur); + } + if( !isView ){ + sqlite3VdbeAddOp2(v, OP_Clear, pTab->tnum, iDb); + if( !pParse->nested ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); + } + } + } + /* The usual case: There is a WHERE clause so we have to scan through + ** the table and pick which records to delete. + */ + else{ + int iRowid = ++pParse->nMem; /* Used for storing rowid values. */ + + /* Begin the database scan + */ + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0); + if( pWInfo==0 ) goto delete_from_cleanup; + + /* Remember the rowid of every item to be deleted. + */ + sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid); + sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid); + if( db->flags & SQLITE_CountRows ){ + sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); + } + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + + /* Open the pseudo-table used to store OLD if there are triggers. + */ + if( triggers_exist ){ + sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol); + } + + /* Delete every item whose key was written to the list during the + ** database scan. We have to delete items after the scan is complete + ** because deleting an item can change the scan order. + */ + end = sqlite3VdbeMakeLabel(v); + + if( !isView ){ + /* Open cursors for the table we are deleting from and + ** all its indices. + */ + sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); + } + + /* This is the beginning of the delete loop. If a trigger encounters + ** an IGNORE constraint, it jumps back to here. + */ + if( triggers_exist ){ + sqlite3VdbeResolveLabel(v, addr); + } + addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end); + + if( triggers_exist ){ + int iData = ++pParse->nMem; /* For storing row data of OLD table */ + + /* If the record is no longer present in the table, jump to the + ** next iteration of the loop through the contents of the fifo. + */ + sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid); + + /* Populate the OLD.* pseudo-table */ + if( old_col_mask ){ + sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, iData); + } + sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid); + + /* Jump back and run the BEFORE triggers */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger); + sqlite3VdbeJumpHere(v, iEndBeforeTrigger); + } + + if( !isView ){ + /* Delete the row */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + const char *pVtab = (const char *)pTab->pVtab; + pParse->pVirtualLock = pTab; + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB); + }else +#endif + { + sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0); + } + } + + /* If there are row triggers, close all cursors then invoke + ** the AFTER triggers + */ + if( triggers_exist ){ + /* Jump back and run the AFTER triggers */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger); + sqlite3VdbeJumpHere(v, iEndAfterTrigger); + } + + /* End of the delete loop */ + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr); + sqlite3VdbeResolveLabel(v, end); + + /* Close the cursors after the loop if there are no row triggers */ + if( !isView && !IsVirtual(pTab) ){ + for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ + sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum); + } + sqlite3VdbeAddOp1(v, OP_Close, iCur); + } + } + + /* + ** Return the number of rows that were deleted. If this routine is + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ + if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P4_STATIC); + } + +delete_from_cleanup: + sqlite3AuthContextPop(&sContext); + sqlite3SrcListDelete(pTabList); + sqlite3ExprDelete(pWhere); + return; +} + +/* +** This routine generates VDBE code that causes a single row of a +** single table to be deleted. +** +** The VDBE must be in a particular state when this routine is called. +** These are the requirements: +** +** 1. A read/write cursor pointing to pTab, the table containing the row +** to be deleted, must be opened as cursor number "base". +** +** 2. Read/write cursors for all indices of pTab must be open as +** cursor number base+i for the i-th index. +** +** 3. The record number of the row to be deleted must be stored in +** memory cell iRowid. +** +** This routine pops the top of the stack to remove the record number +** and then generates code to remove both the table record and all index +** entries that point to that record. +*/ +void sqlite3GenerateRowDelete( + Parse *pParse, /* Parsing context */ + Table *pTab, /* Table containing the row to be deleted */ + int iCur, /* Cursor number for the table */ + int iRowid, /* Memory cell that contains the rowid to delete */ + int count /* Increment the row change counter */ +){ + int addr; + Vdbe *v; + + v = pParse->pVdbe; + addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid); + sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0); + sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); + if( count ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + sqlite3VdbeJumpHere(v, addr); +} + +/* +** This routine generates VDBE code that causes the deletion of all +** index entries associated with a single row of a single table. +** +** The VDBE must be in a particular state when this routine is called. +** These are the requirements: +** +** 1. A read/write cursor pointing to pTab, the table containing the row +** to be deleted, must be opened as cursor number "iCur". +** +** 2. Read/write cursors for all indices of pTab must be open as +** cursor number iCur+i for the i-th index. +** +** 3. The "iCur" cursor must be pointing to the row that is to be +** deleted. +*/ +void sqlite3GenerateRowIndexDelete( + Parse *pParse, /* Parsing and code generating context */ + Table *pTab, /* Table containing the row to be deleted */ + int iCur, /* Cursor number for the table */ + int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */ +){ + int i; + Index *pIdx; + int r1; + + r1 = sqlite3GetTempReg(pParse); + for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ + if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; + sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1); + sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1); + } + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Generate code that will assemble an index key and put it on the top +** of the tack. The key with be for index pIdx which is an index on pTab. +** iCur is the index of a cursor open on the pTab table and pointing to +** the entry that needs indexing. +** +** Return a register number which is the first in a block of +** registers that holds the elements of the index key. The +** block of registers has already been deallocated by the time +** this routine returns. +*/ +int sqlite3GenerateIndexKey( + Parse *pParse, /* Parsing context */ + Index *pIdx, /* The index for which to generate a key */ + int iCur, /* Cursor number for the pIdx->pTable table */ + int regOut /* Write the new index key to this register */ +){ + Vdbe *v = pParse->pVdbe; + int j; + Table *pTab = pIdx->pTable; + int regBase; + int nCol; + + nCol = pIdx->nColumn; + regBase = sqlite3GetTempRange(pParse, nCol+1); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol); + for(j=0; jaiColumn[j]; + if( idx==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j); + }else{ + sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j); + sqlite3ColumnDefault(v, pTab, idx); + } + } + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ReleaseTempRange(pParse, regBase, nCol+1); + return regBase; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/experimental.c b/client/src/thirdparty/sqlite-3.4.2/src/experimental.c new file mode 100644 index 0000000..052eb0b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/experimental.c @@ -0,0 +1,37 @@ +/* +** 2005 January 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 C code routines that are not a part of the official +** SQLite API. These routines are unsupported. +** +** $Id: experimental.c,v 1.4 2006/01/31 20:49:13 drh Exp $ +*/ +#include "sqliteInt.h" +#include "os.h" + +/* +** Set all the parameters in the compiled SQL statement to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ + rc = sqlite3_bind_null(pStmt, i); + } + return rc; +} + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +int sqlite3_sleep(int ms){ + return sqlite3OsSleep(ms); +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/expr.c b/client/src/thirdparty/sqlite-3.4.2/src/expr.c new file mode 100644 index 0000000..e74bdd1 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/expr.c @@ -0,0 +1,2983 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains routines used for analyzing expressions and +** for generating VDBE code that evaluates expressions in SQLite. +** +** $Id: expr.c,v 1.352 2008/01/23 14:51:49 drh Exp $ +*/ +#include "sqliteInt.h" +#include + +/* +** Return the 'affinity' of the expression pExpr if any. +** +** If pExpr is a column, a reference to a column via an 'AS' alias, +** or a sub-select with a column as the return value, then the +** affinity of that column is returned. Otherwise, 0x00 is returned, +** indicating no affinity for the expression. +** +** i.e. the WHERE clause expresssions in the following statements all +** have an affinity: +** +** CREATE TABLE t1(a); +** SELECT * FROM t1 WHERE a; +** SELECT a AS b FROM t1 WHERE b; +** SELECT * FROM t1 WHERE (select a from t1); +*/ +char sqlite3ExprAffinity(Expr *pExpr){ + int op = pExpr->op; + if( op==TK_SELECT ){ + return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); + } +#ifndef SQLITE_OMIT_CAST + if( op==TK_CAST ){ + return sqlite3AffinityType(&pExpr->token); + } +#endif + return pExpr->affinity; +} + +/* +** Set the collating sequence for expression pExpr to be the collating +** sequence named by pToken. Return a pointer to the revised expression. +** The collating sequence is marked as "explicit" using the EP_ExpCollate +** flag. An explicit collating sequence will override implicit +** collating sequences. +*/ +Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ + char *zColl = 0; /* Dequoted name of collation sequence */ + CollSeq *pColl; + zColl = sqlite3NameFromToken(pParse->db, pName); + if( pExpr && zColl ){ + pColl = sqlite3LocateCollSeq(pParse, zColl, -1); + if( pColl ){ + pExpr->pColl = pColl; + pExpr->flags |= EP_ExpCollate; + } + } + sqlite3_free(zColl); + return pExpr; +} + +/* +** Return the default collation sequence for the expression pExpr. If +** there is no default collation type, return 0. +*/ +CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ + CollSeq *pColl = 0; + if( pExpr ){ + int op; + pColl = pExpr->pColl; + op = pExpr->op; + if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){ + return sqlite3ExprCollSeq(pParse, pExpr->pLeft); + } + } + if( sqlite3CheckCollSeq(pParse, pColl) ){ + pColl = 0; + } + return pColl; +} + +/* +** pExpr is an operand of a comparison operator. aff2 is the +** type affinity of the other operand. This routine returns the +** type affinity that should be used for the comparison operator. +*/ +char sqlite3CompareAffinity(Expr *pExpr, char aff2){ + char aff1 = sqlite3ExprAffinity(pExpr); + if( aff1 && aff2 ){ + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. + */ + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ + return SQLITE_AFF_NUMERIC; + }else{ + return SQLITE_AFF_NONE; + } + }else if( !aff1 && !aff2 ){ + /* Neither side of the comparison is a column. Compare the + ** results directly. + */ + return SQLITE_AFF_NONE; + }else{ + /* One side is a column, the other is not. Use the columns affinity. */ + assert( aff1==0 || aff2==0 ); + return (aff1 + aff2); + } +} + +/* +** pExpr is a comparison operator. Return the type affinity that should +** be applied to both operands prior to doing the comparison. +*/ +static char comparisonAffinity(Expr *pExpr){ + char aff; + assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || + pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || + pExpr->op==TK_NE ); + assert( pExpr->pLeft ); + aff = sqlite3ExprAffinity(pExpr->pLeft); + if( pExpr->pRight ){ + aff = sqlite3CompareAffinity(pExpr->pRight, aff); + } + else if( pExpr->pSelect ){ + aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff); + } + else if( !aff ){ + aff = SQLITE_AFF_NONE; + } + return aff; +} + +/* +** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. +** idx_affinity is the affinity of an indexed column. Return true +** if the index with affinity idx_affinity may be used to implement +** the comparison in pExpr. +*/ +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ + char aff = comparisonAffinity(pExpr); + switch( aff ){ + case SQLITE_AFF_NONE: + return 1; + case SQLITE_AFF_TEXT: + return idx_affinity==SQLITE_AFF_TEXT; + default: + return sqlite3IsNumericAffinity(idx_affinity); + } +} + +/* +** Return the P5 value that should be used for a binary comparison +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. +*/ +static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ + u8 aff = (char)sqlite3ExprAffinity(pExpr2); + aff = sqlite3CompareAffinity(pExpr1, aff) | jumpIfNull; + return aff; +} + +/* +** Return a pointer to the collation sequence that should be used by +** a binary comparison operator comparing pLeft and pRight. +** +** If the left hand expression has a collating sequence type, then it is +** used. Otherwise the collation sequence for the right hand expression +** is used, or the default (BINARY) if neither expression has a collating +** type. +** +** Argument pRight (but not pLeft) may be a null pointer. In this case, +** it is not considered. +*/ +CollSeq *sqlite3BinaryCompareCollSeq( + Parse *pParse, + Expr *pLeft, + Expr *pRight +){ + CollSeq *pColl; + assert( pLeft ); + if( pLeft->flags & EP_ExpCollate ){ + assert( pLeft->pColl ); + pColl = pLeft->pColl; + }else if( pRight && pRight->flags & EP_ExpCollate ){ + assert( pRight->pColl ); + pColl = pRight->pColl; + }else{ + pColl = sqlite3ExprCollSeq(pParse, pLeft); + if( !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pRight); + } + } + return pColl; +} + +/* +** Generate code for a comparison operator. +*/ +static int codeCompare( + Parse *pParse, /* The parsing (and code generating) context */ + Expr *pLeft, /* The left operand */ + Expr *pRight, /* The right operand */ + int opcode, /* The comparison opcode */ + int in1, int in2, /* Register holding operands */ + int dest, /* Jump here if true. */ + int jumpIfNull /* If true, jump if either operand is NULL */ +){ + int p5; + int addr; + CollSeq *p4; + + p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); + p5 = binaryCompareP5(pLeft, pRight, jumpIfNull); + addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1, + (void*)p4, P4_COLLSEQ); + sqlite3VdbeChangeP5(pParse->pVdbe, p5); + return addr; +} + +/* +** Construct a new expression node and return a pointer to it. Memory +** for this node is obtained from sqlite3_malloc(). The calling function +** is responsible for making sure the node eventually gets freed. +*/ +Expr *sqlite3Expr( + sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ + int op, /* Expression opcode */ + Expr *pLeft, /* Left operand */ + Expr *pRight, /* Right operand */ + const Token *pToken /* Argument token */ +){ + Expr *pNew; + pNew = sqlite3DbMallocZero(db, sizeof(Expr)); + if( pNew==0 ){ + /* When malloc fails, delete pLeft and pRight. Expressions passed to + ** this function must always be allocated with sqlite3Expr() for this + ** reason. + */ + sqlite3ExprDelete(pLeft); + sqlite3ExprDelete(pRight); + return 0; + } + pNew->op = op; + pNew->pLeft = pLeft; + pNew->pRight = pRight; + pNew->iAgg = -1; + if( pToken ){ + assert( pToken->dyn==0 ); + pNew->span = pNew->token = *pToken; + }else if( pLeft ){ + if( pRight ){ + sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); + if( pRight->flags & EP_ExpCollate ){ + pNew->flags |= EP_ExpCollate; + pNew->pColl = pRight->pColl; + } + } + if( pLeft->flags & EP_ExpCollate ){ + pNew->flags |= EP_ExpCollate; + pNew->pColl = pLeft->pColl; + } + } + + sqlite3ExprSetHeight(pNew); + return pNew; +} + +/* +** Works like sqlite3Expr() except that it takes an extra Parse* +** argument and notifies the associated connection object if malloc fails. +*/ +Expr *sqlite3PExpr( + Parse *pParse, /* Parsing context */ + int op, /* Expression opcode */ + Expr *pLeft, /* Left operand */ + Expr *pRight, /* Right operand */ + const Token *pToken /* Argument token */ +){ + return sqlite3Expr(pParse->db, op, pLeft, pRight, pToken); +} + +/* +** When doing a nested parse, you can include terms in an expression +** that look like this: #1 #2 ... These terms refer to registers +** in the virtual machine. #N is the N-th register. +** +** This routine is called by the parser to deal with on of those terms. +** It immediately generates code to store the value in a memory location. +** The returns an expression that will code to extract the value from +** that memory location as needed. +*/ +Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ + Vdbe *v = pParse->pVdbe; + Expr *p; + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); + return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0); + } + if( v==0 ) return 0; + p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken); + if( p==0 ){ + return 0; /* Malloc failed */ + } + p->iTable = atoi((char*)&pToken->z[1]); + return p; +} + +/* +** Join two expressions using an AND operator. If either expression is +** NULL, then just return the other expression. +*/ +Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ + if( pLeft==0 ){ + return pRight; + }else if( pRight==0 ){ + return pLeft; + }else{ + return sqlite3Expr(db, TK_AND, pLeft, pRight, 0); + } +} + +/* +** Set the Expr.span field of the given expression to span all +** text between the two given tokens. +*/ +void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ + assert( pRight!=0 ); + assert( pLeft!=0 ); + if( pExpr && pRight->z && pLeft->z ){ + assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 ); + if( pLeft->dyn==0 && pRight->dyn==0 ){ + pExpr->span.z = pLeft->z; + pExpr->span.n = pRight->n + (pRight->z - pLeft->z); + }else{ + pExpr->span.z = 0; + } + } +} + +/* +** Construct a new expression node for a function with multiple +** arguments. +*/ +Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ + Expr *pNew; + assert( pToken ); + pNew = sqlite3DbMallocZero(pParse->db, sizeof(Expr) ); + if( pNew==0 ){ + sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */ + return 0; + } + pNew->op = TK_FUNCTION; + pNew->pList = pList; + assert( pToken->dyn==0 ); + pNew->token = *pToken; + pNew->span = pNew->token; + + sqlite3ExprSetHeight(pNew); + return pNew; +} + +/* +** Assign a variable number to an expression that encodes a wildcard +** in the original SQL statement. +** +** Wildcards consisting of a single "?" are assigned the next sequential +** variable number. +** +** Wildcards of the form "?nnn" are assigned the number "nnn". We make +** sure "nnn" is not too be to avoid a denial of service attack when +** the SQL statement comes from an external source. +** +** Wildcards of the form ":aaa" or "$aaa" are assigned the same number +** as the previous instance of the same wildcard. Or if this is the first +** instance of the wildcard, the next sequenial variable number is +** assigned. +*/ +void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ + Token *pToken; + sqlite3 *db = pParse->db; + + if( pExpr==0 ) return; + pToken = &pExpr->token; + assert( pToken->n>=1 ); + assert( pToken->z!=0 ); + assert( pToken->z[0]!=0 ); + if( pToken->n==1 ){ + /* Wildcard of the form "?". Assign the next variable number */ + pExpr->iTable = ++pParse->nVar; + }else if( pToken->z[0]=='?' ){ + /* Wildcard of the form "?nnn". Convert "nnn" to an integer and + ** use it as the variable number */ + int i; + pExpr->iTable = i = atoi((char*)&pToken->z[1]); + if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ + sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", + SQLITE_MAX_VARIABLE_NUMBER); + } + if( i>pParse->nVar ){ + pParse->nVar = i; + } + }else{ + /* Wildcards of the form ":aaa" or "$aaa". Reuse the same variable + ** number as the prior appearance of the same name, or if the name + ** has never appeared before, reuse the same variable number + */ + int i, n; + n = pToken->n; + for(i=0; inVarExpr; i++){ + Expr *pE; + if( (pE = pParse->apVarExpr[i])!=0 + && pE->token.n==n + && memcmp(pE->token.z, pToken->z, n)==0 ){ + pExpr->iTable = pE->iTable; + break; + } + } + if( i>=pParse->nVarExpr ){ + pExpr->iTable = ++pParse->nVar; + if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ + pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; + pParse->apVarExpr = + sqlite3DbReallocOrFree( + db, + pParse->apVarExpr, + pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) + ); + } + if( !db->mallocFailed ){ + assert( pParse->apVarExpr!=0 ); + pParse->apVarExpr[pParse->nVarExpr++] = pExpr; + } + } + } + if( !pParse->nErr && pParse->nVar>SQLITE_MAX_VARIABLE_NUMBER ){ + sqlite3ErrorMsg(pParse, "too many SQL variables"); + } +} + +/* +** Recursively delete an expression tree. +*/ +void sqlite3ExprDelete(Expr *p){ + if( p==0 ) return; + if( p->span.dyn ) sqlite3_free((char*)p->span.z); + if( p->token.dyn ) sqlite3_free((char*)p->token.z); + sqlite3ExprDelete(p->pLeft); + sqlite3ExprDelete(p->pRight); + sqlite3ExprListDelete(p->pList); + sqlite3SelectDelete(p->pSelect); + sqlite3_free(p); +} + +/* +** The Expr.token field might be a string literal that is quoted. +** If so, remove the quotation marks. +*/ +void sqlite3DequoteExpr(sqlite3 *db, Expr *p){ + if( ExprHasAnyProperty(p, EP_Dequoted) ){ + return; + } + ExprSetProperty(p, EP_Dequoted); + if( p->token.dyn==0 ){ + sqlite3TokenCopy(db, &p->token, &p->token); + } + sqlite3Dequote((char*)p->token.z); +} + + +/* +** The following group of routines make deep copies of expressions, +** expression lists, ID lists, and select statements. The copies can +** be deleted (by being passed to their respective ...Delete() routines) +** without effecting the originals. +** +** The expression list, ID, and source lists return by sqlite3ExprListDup(), +** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded +** by subsequent calls to sqlite*ListAppend() routines. +** +** Any tables that the SrcList might point to are not duplicated. +*/ +Expr *sqlite3ExprDup(sqlite3 *db, Expr *p){ + Expr *pNew; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); + if( pNew==0 ) return 0; + memcpy(pNew, p, sizeof(*pNew)); + if( p->token.z!=0 ){ + pNew->token.z = (u8*)sqlite3DbStrNDup(db, (char*)p->token.z, p->token.n); + pNew->token.dyn = 1; + }else{ + assert( pNew->token.z==0 ); + } + pNew->span.z = 0; + pNew->pLeft = sqlite3ExprDup(db, p->pLeft); + pNew->pRight = sqlite3ExprDup(db, p->pRight); + pNew->pList = sqlite3ExprListDup(db, p->pList); + pNew->pSelect = sqlite3SelectDup(db, p->pSelect); + return pNew; +} +void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){ + if( pTo->dyn ) sqlite3_free((char*)pTo->z); + if( pFrom->z ){ + pTo->n = pFrom->n; + pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n); + pTo->dyn = 1; + }else{ + pTo->z = 0; + } +} +ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){ + ExprList *pNew; + struct ExprList_item *pItem, *pOldItem; + int i; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->iECursor = 0; + pNew->nExpr = pNew->nAlloc = p->nExpr; + pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) ); + if( pItem==0 ){ + sqlite3_free(pNew); + return 0; + } + pOldItem = p->a; + for(i=0; inExpr; i++, pItem++, pOldItem++){ + Expr *pNewExpr, *pOldExpr; + pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr = pOldItem->pExpr); + if( pOldExpr->span.z!=0 && pNewExpr ){ + /* Always make a copy of the span for top-level expressions in the + ** expression list. The logic in SELECT processing that determines + ** the names of columns in the result set needs this information */ + sqlite3TokenCopy(db, &pNewExpr->span, &pOldExpr->span); + } + assert( pNewExpr==0 || pNewExpr->span.z!=0 + || pOldExpr->span.z==0 + || db->mallocFailed ); + pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pItem->sortOrder = pOldItem->sortOrder; + pItem->isAgg = pOldItem->isAgg; + pItem->done = 0; + } + return pNew; +} + +/* +** If cursors, triggers, views and subqueries are all omitted from +** the build, then none of the following routines, except for +** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes +** called with a NULL argument. +*/ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ + || !defined(SQLITE_OMIT_SUBQUERY) +SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p){ + SrcList *pNew; + int i; + int nByte; + if( p==0 ) return 0; + nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); + pNew = sqlite3DbMallocRaw(db, nByte ); + if( pNew==0 ) return 0; + pNew->nSrc = pNew->nAlloc = p->nSrc; + for(i=0; inSrc; i++){ + struct SrcList_item *pNewItem = &pNew->a[i]; + struct SrcList_item *pOldItem = &p->a[i]; + Table *pTab; + pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); + pNewItem->jointype = pOldItem->jointype; + pNewItem->iCursor = pOldItem->iCursor; + pNewItem->isPopulated = pOldItem->isPopulated; + pTab = pNewItem->pTab = pOldItem->pTab; + if( pTab ){ + pTab->nRef++; + } + pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect); + pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn); + pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); + pNewItem->colUsed = pOldItem->colUsed; + } + return pNew; +} +IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ + IdList *pNew; + int i; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nId = pNew->nAlloc = p->nId; + pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); + if( pNew->a==0 ){ + sqlite3_free(pNew); + return 0; + } + for(i=0; inId; i++){ + struct IdList_item *pNewItem = &pNew->a[i]; + struct IdList_item *pOldItem = &p->a[i]; + pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); + pNewItem->idx = pOldItem->idx; + } + return pNew; +} +Select *sqlite3SelectDup(sqlite3 *db, Select *p){ + Select *pNew; + if( p==0 ) return 0; + pNew = sqlite3DbMallocRaw(db, sizeof(*p) ); + if( pNew==0 ) return 0; + pNew->isDistinct = p->isDistinct; + pNew->pEList = sqlite3ExprListDup(db, p->pEList); + pNew->pSrc = sqlite3SrcListDup(db, p->pSrc); + pNew->pWhere = sqlite3ExprDup(db, p->pWhere); + pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy); + pNew->pHaving = sqlite3ExprDup(db, p->pHaving); + pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy); + pNew->op = p->op; + pNew->pPrior = sqlite3SelectDup(db, p->pPrior); + pNew->pLimit = sqlite3ExprDup(db, p->pLimit); + pNew->pOffset = sqlite3ExprDup(db, p->pOffset); + pNew->iLimit = -1; + pNew->iOffset = -1; + pNew->isResolved = p->isResolved; + pNew->isAgg = p->isAgg; + pNew->usesEphm = 0; + pNew->disallowOrderBy = 0; + pNew->pRightmost = 0; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + return pNew; +} +#else +Select *sqlite3SelectDup(sqlite3 *db, Select *p){ + assert( p==0 ); + return 0; +} +#endif + + +/* +** Add a new element to the end of an expression list. If pList is +** initially NULL, then create a new expression list. +*/ +ExprList *sqlite3ExprListAppend( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List to which to append. Might be NULL */ + Expr *pExpr, /* Expression to be appended */ + Token *pName /* AS keyword for the expression */ +){ + sqlite3 *db = pParse->db; + if( pList==0 ){ + pList = sqlite3DbMallocZero(db, sizeof(ExprList) ); + if( pList==0 ){ + goto no_mem; + } + assert( pList->nAlloc==0 ); + } + if( pList->nAlloc<=pList->nExpr ){ + struct ExprList_item *a; + int n = pList->nAlloc*2 + 4; + a = sqlite3DbRealloc(db, pList->a, n*sizeof(pList->a[0])); + if( a==0 ){ + goto no_mem; + } + pList->a = a; + pList->nAlloc = n; + } + assert( pList->a!=0 ); + if( pExpr || pName ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr++]; + memset(pItem, 0, sizeof(*pItem)); + pItem->zName = sqlite3NameFromToken(db, pName); + pItem->pExpr = pExpr; + } + return pList; + +no_mem: + /* Avoid leaking memory if malloc has failed. */ + sqlite3ExprDelete(pExpr); + sqlite3ExprListDelete(pList); + return 0; +} + +/* +** If the expression list pEList contains more than iLimit elements, +** leave an error message in pParse. +*/ +void sqlite3ExprListCheckLength( + Parse *pParse, + ExprList *pEList, + int iLimit, + const char *zObject +){ + if( pEList && pEList->nExpr>iLimit ){ + sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); + } +} + + +#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 +/* The following three functions, heightOfExpr(), heightOfExprList() +** and heightOfSelect(), are used to determine the maximum height +** of any expression tree referenced by the structure passed as the +** first argument. +** +** If this maximum height is greater than the current value pointed +** to by pnHeight, the second parameter, then set *pnHeight to that +** value. +*/ +static void heightOfExpr(Expr *p, int *pnHeight){ + if( p ){ + if( p->nHeight>*pnHeight ){ + *pnHeight = p->nHeight; + } + } +} +static void heightOfExprList(ExprList *p, int *pnHeight){ + if( p ){ + int i; + for(i=0; inExpr; i++){ + heightOfExpr(p->a[i].pExpr, pnHeight); + } + } +} +static void heightOfSelect(Select *p, int *pnHeight){ + if( p ){ + heightOfExpr(p->pWhere, pnHeight); + heightOfExpr(p->pHaving, pnHeight); + heightOfExpr(p->pLimit, pnHeight); + heightOfExpr(p->pOffset, pnHeight); + heightOfExprList(p->pEList, pnHeight); + heightOfExprList(p->pGroupBy, pnHeight); + heightOfExprList(p->pOrderBy, pnHeight); + heightOfSelect(p->pPrior, pnHeight); + } +} + +/* +** Set the Expr.nHeight variable in the structure passed as an +** argument. An expression with no children, Expr.pList or +** 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. +*/ +void sqlite3ExprSetHeight(Expr *p){ + int nHeight = 0; + heightOfExpr(p->pLeft, &nHeight); + heightOfExpr(p->pRight, &nHeight); + heightOfExprList(p->pList, &nHeight); + heightOfSelect(p->pSelect, &nHeight); + p->nHeight = nHeight + 1; +} + +/* +** Return the maximum height of any expression tree referenced +** by the select statement passed as an argument. +*/ +int sqlite3SelectExprHeight(Select *p){ + int nHeight = 0; + heightOfSelect(p, &nHeight); + return nHeight; +} +#endif + +/* +** Delete an entire expression list. +*/ +void sqlite3ExprListDelete(ExprList *pList){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return; + assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); + assert( pList->nExpr<=pList->nAlloc ); + for(pItem=pList->a, i=0; inExpr; i++, pItem++){ + sqlite3ExprDelete(pItem->pExpr); + sqlite3_free(pItem->zName); + } + sqlite3_free(pList->a); + sqlite3_free(pList); +} + +/* +** Walk an expression tree. Call xFunc for each node visited. +** +** The return value from xFunc determines whether the tree walk continues. +** 0 means continue walking the tree. 1 means do not walk children +** of the current node but continue with siblings. 2 means abandon +** the tree walk completely. +** +** The return value from this routine is 1 to abandon the tree walk +** and 0 to continue. +** +** NOTICE: This routine does *not* descend into subqueries. +*/ +static int walkExprList(ExprList *, int (*)(void *, Expr*), void *); +static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){ + int rc; + if( pExpr==0 ) return 0; + rc = (*xFunc)(pArg, pExpr); + if( rc==0 ){ + if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1; + if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1; + if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1; + } + return rc>1; +} + +/* +** Call walkExprTree() for every expression in list p. +*/ +static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){ + int i; + struct ExprList_item *pItem; + if( !p ) return 0; + for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ + if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1; + } + return 0; +} + +/* +** Call walkExprTree() for every expression in Select p, not including +** expressions that are part of sub-selects in any FROM clause or the LIMIT +** or OFFSET expressions.. +*/ +static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){ + walkExprList(p->pEList, xFunc, pArg); + walkExprTree(p->pWhere, xFunc, pArg); + walkExprList(p->pGroupBy, xFunc, pArg); + walkExprTree(p->pHaving, xFunc, pArg); + walkExprList(p->pOrderBy, xFunc, pArg); + if( p->pPrior ){ + walkSelectExpr(p->pPrior, xFunc, pArg); + } + return 0; +} + + +/* +** This routine is designed as an xFunc for walkExprTree(). +** +** pArg is really a pointer to an integer. If we can tell by looking +** at pExpr that the expression that contains pExpr is not a constant +** expression, then set *pArg to 0 and return 2 to abandon the tree walk. +** If pExpr does does not disqualify the expression from being a constant +** then do nothing. +** +** After walking the whole tree, if no nodes are found that disqualify +** the expression as constant, then we assume the whole expression +** is constant. See sqlite3ExprIsConstant() for additional information. +*/ +static int exprNodeIsConstant(void *pArg, Expr *pExpr){ + int *pN = (int*)pArg; + + /* If *pArg is 3 then any term of the expression that comes from + ** the ON or USING clauses of a join disqualifies the expression + ** from being considered constant. */ + if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){ + *pN = 0; + return 2; + } + + switch( pExpr->op ){ + /* Consider functions to be constant if all their arguments are constant + ** and *pArg==2 */ + case TK_FUNCTION: + if( (*pN)==2 ) return 0; + /* Fall through */ + case TK_ID: + case TK_COLUMN: + case TK_DOT: + case TK_AGG_FUNCTION: + case TK_AGG_COLUMN: +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: +#endif + *pN = 0; + return 2; + case TK_IN: + if( pExpr->pSelect ){ + *pN = 0; + return 2; + } + default: + return 0; + } +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** and 0 if it involves variables or function calls. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +int sqlite3ExprIsConstant(Expr *p){ + int isConst = 1; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst; +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** that does no originate from the ON or USING clauses of a join. +** Return 0 if it involves variables or function calls or terms from +** an ON or USING clause. +*/ +int sqlite3ExprIsConstantNotJoin(Expr *p){ + int isConst = 3; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst!=0; +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** or a function call with constant arguments. Return and 0 if there +** are any variables. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +int sqlite3ExprIsConstantOrFunction(Expr *p){ + int isConst = 2; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst!=0; +} + +/* +** If the expression p codes a constant integer that is small enough +** to fit in a 32-bit integer, return 1 and put the value of the integer +** in *pValue. If the expression is not an integer or if it is too big +** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. +*/ +int sqlite3ExprIsInteger(Expr *p, int *pValue){ + switch( p->op ){ + case TK_INTEGER: { + if( sqlite3GetInt32((char*)p->token.z, pValue) ){ + return 1; + } + break; + } + case TK_UPLUS: { + return sqlite3ExprIsInteger(p->pLeft, pValue); + } + case TK_UMINUS: { + int v; + if( sqlite3ExprIsInteger(p->pLeft, &v) ){ + *pValue = -v; + return 1; + } + break; + } + default: break; + } + return 0; +} + +/* +** Return TRUE if the given string is a row-id column name. +*/ +int sqlite3IsRowid(const char *z){ + if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; + if( sqlite3StrICmp(z, "ROWID")==0 ) return 1; + if( sqlite3StrICmp(z, "OID")==0 ) return 1; + return 0; +} + +/* +** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up +** that name in the set of source tables in pSrcList and make the pExpr +** expression node refer back to that source column. The following changes +** are made to pExpr: +** +** pExpr->iDb Set the index in db->aDb[] of the database holding +** the table. +** pExpr->iTable Set to the cursor number for the table obtained +** from pSrcList. +** pExpr->iColumn Set to the column number within the table. +** pExpr->op Set to TK_COLUMN. +** pExpr->pLeft Any expression this points to is deleted +** pExpr->pRight Any expression this points to is deleted. +** +** The pDbToken is the name of the database (the "X"). This value may be +** NULL meaning that name is of the form Y.Z or Z. Any available database +** can be used. The pTableToken is the name of the table (the "Y"). This +** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it +** means that the form of the name is Z and that columns from any table +** can be used. +** +** If the name cannot be resolved unambiguously, leave an error message +** in pParse and return non-zero. Return zero on success. +*/ +static int lookupName( + Parse *pParse, /* The parsing context */ + Token *pDbToken, /* Name of the database containing table, or NULL */ + Token *pTableToken, /* Name of table containing column, or NULL */ + Token *pColumnToken, /* Name of the column. */ + NameContext *pNC, /* The name context used to resolve the name */ + Expr *pExpr /* Make this EXPR node point to the selected column */ +){ + char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ + char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ + char *zCol = 0; /* Name of the column. The "Z" */ + int i, j; /* Loop counters */ + int cnt = 0; /* Number of matching column names */ + int cntTab = 0; /* Number of matching table names */ + sqlite3 *db = pParse->db; /* The database */ + struct SrcList_item *pItem; /* Use for looping over pSrcList items */ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ + NameContext *pTopNC = pNC; /* First namecontext in the list */ + Schema *pSchema = 0; /* Schema of the expression */ + + assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ + zDb = sqlite3NameFromToken(db, pDbToken); + zTab = sqlite3NameFromToken(db, pTableToken); + zCol = sqlite3NameFromToken(db, pColumnToken); + if( db->mallocFailed ){ + goto lookupname_end; + } + + pExpr->iTable = -1; + while( pNC && cnt==0 ){ + ExprList *pEList; + SrcList *pSrcList = pNC->pSrcList; + + if( pSrcList ){ + for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ + Table *pTab; + int iDb; + Column *pCol; + + pTab = pItem->pTab; + assert( pTab!=0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( pTab->nCol>0 ); + if( zTab ){ + if( pItem->zAlias ){ + char *zTabName = pItem->zAlias; + if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + }else{ + char *zTabName = pTab->zName; + if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ + continue; + } + } + } + if( 0==(cntTab++) ){ + pExpr->iTable = pItem->iCursor; + pSchema = pTab->pSchema; + pMatch = pItem; + } + for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[j].zColl; + IdList *pUsing; + cnt++; + pExpr->iTable = pItem->iCursor; + pMatch = pItem; + pSchema = pTab->pSchema; + /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ + pExpr->iColumn = j==pTab->iPKey ? -1 : j; + pExpr->affinity = pTab->aCol[j].affinity; + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } + if( inSrc-1 ){ + if( pItem[1].jointype & JT_NATURAL ){ + /* If this match occurred in the left table of a natural join, + ** then skip the right table to avoid a duplicate match */ + pItem++; + i++; + }else if( (pUsing = pItem[1].pUsing)!=0 ){ + /* If this match occurs on a column that is in the USING clause + ** of a join, skip the search of the right table of the join + ** to avoid a duplicate match there. */ + int k; + for(k=0; knId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){ + pItem++; + i++; + break; + } + } + } + } + break; + } + } + } + } + +#ifndef SQLITE_OMIT_TRIGGER + /* If we have not already resolved the name, then maybe + ** it is a new.* or old.* trigger argument reference + */ + if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ + TriggerStack *pTriggerStack = pParse->trigStack; + Table *pTab = 0; + u32 *piColMask; + if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){ + pExpr->iTable = pTriggerStack->newIdx; + assert( pTriggerStack->pTab ); + pTab = pTriggerStack->pTab; + piColMask = &(pTriggerStack->newColMask); + }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){ + pExpr->iTable = pTriggerStack->oldIdx; + assert( pTriggerStack->pTab ); + pTab = pTriggerStack->pTab; + piColMask = &(pTriggerStack->oldColMask); + } + + if( pTab ){ + int iCol; + Column *pCol = pTab->aCol; + + pSchema = pTab->pSchema; + cntTab++; + for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) { + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[iCol].zColl; + cnt++; + pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; + pExpr->affinity = pTab->aCol[iCol].affinity; + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } + pExpr->pTab = pTab; + if( iCol>=0 ){ + *piColMask |= ((u32)1<=32?0xffffffff:0); + } + break; + } + } + } + } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ + + /* + ** Perhaps the name is a reference to the ROWID + */ + if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){ + cnt = 1; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; + } + + /* + ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z + ** might refer to an result-set alias. This happens, for example, when + ** we are resolving names in the WHERE clause of the following command: + ** + ** SELECT a+b AS x FROM table WHERE x<10; + ** + ** In cases like this, replace pExpr with a copy of the expression that + ** forms the result set entry ("a+b" in the example) and return immediately. + ** Note that the expression in the result set should have already been + ** resolved by the time the WHERE clause is resolved. + */ + if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){ + for(j=0; jnExpr; j++){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + Expr *pDup, *pOrig; + assert( pExpr->pLeft==0 && pExpr->pRight==0 ); + assert( pExpr->pList==0 ); + assert( pExpr->pSelect==0 ); + pOrig = pEList->a[j].pExpr; + if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); + sqlite3_free(zCol); + return 2; + } + pDup = sqlite3ExprDup(db, pOrig); + if( pExpr->flags & EP_ExpCollate ){ + pDup->pColl = pExpr->pColl; + pDup->flags |= EP_ExpCollate; + } + if( pExpr->span.dyn ) sqlite3_free((char*)pExpr->span.z); + if( pExpr->token.dyn ) sqlite3_free((char*)pExpr->token.z); + memcpy(pExpr, pDup, sizeof(*pExpr)); + sqlite3_free(pDup); + cnt = 1; + pMatch = 0; + assert( zTab==0 && zDb==0 ); + goto lookupname_end_2; + } + } + } + + /* Advance to the next name context. The loop will exit when either + ** we have a match (cnt>0) or when we run out of name contexts. + */ + if( cnt==0 ){ + pNC = pNC->pNext; + } + } + + /* + ** If X and Y are NULL (in other words if only the column name Z is + ** supplied) and the value of Z is enclosed in double-quotes, then + ** Z is a string literal if it doesn't match any column names. In that + ** case, we need to return right away and not make any changes to + ** pExpr. + ** + ** Because no reference was made to outer contexts, the pNC->nRef + ** fields are not changed in any context. + */ + if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ + sqlite3_free(zCol); + return 0; + } + + /* + ** cnt==0 means there was not match. cnt>1 means there were two or + ** more matches. Either way, we have an error. + */ + if( cnt!=1 ){ + const char *zErr; + zErr = cnt==0 ? "no such column" : "ambiguous column name"; + if( zDb ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); + }else if( zTab ){ + sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol); + }else{ + sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); + } + pTopNC->nErr++; + } + + /* If a column from a table in pSrcList is referenced, then record + ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes + ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the + ** column number is greater than the number of bits in the bitmask + ** then set the high-order bit of the bitmask. + */ + if( pExpr->iColumn>=0 && pMatch!=0 ){ + int n = pExpr->iColumn; + if( n>=sizeof(Bitmask)*8 ){ + n = sizeof(Bitmask)*8-1; + } + assert( pMatch->iCursor==pExpr->iTable ); + pMatch->colUsed |= ((Bitmask)1)<pLeft); + pExpr->pLeft = 0; + sqlite3ExprDelete(pExpr->pRight); + pExpr->pRight = 0; + pExpr->op = TK_COLUMN; +lookupname_end_2: + sqlite3_free(zCol); + if( cnt==1 ){ + assert( pNC!=0 ); + sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); + if( pMatch && !pMatch->pSelect ){ + pExpr->pTab = pMatch->pTab; + } + /* Increment the nRef value on all name contexts from TopNC up to + ** the point where the name matched. */ + for(;;){ + assert( pTopNC!=0 ); + pTopNC->nRef++; + if( pTopNC==pNC ) break; + pTopNC = pTopNC->pNext; + } + return 0; + } else { + return 1; + } +} + +/* +** This routine is designed as an xFunc for walkExprTree(). +** +** Resolve symbolic names into TK_COLUMN operators for the current +** node in the expression tree. Return 0 to continue the search down +** the tree or 2 to abort the tree walk. +** +** This routine also does error checking and name resolution for +** function names. The operator for aggregate functions is changed +** to TK_AGG_FUNCTION. +*/ +static int nameResolverStep(void *pArg, Expr *pExpr){ + NameContext *pNC = (NameContext*)pArg; + Parse *pParse; + + if( pExpr==0 ) return 1; + assert( pNC!=0 ); + pParse = pNC->pParse; + + if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; + ExprSetProperty(pExpr, EP_Resolved); +#ifndef NDEBUG + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ + SrcList *pSrcList = pNC->pSrcList; + int i; + for(i=0; ipSrcList->nSrc; i++){ + assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); + } + } +#endif + switch( pExpr->op ){ + /* Double-quoted strings (ex: "abc") are used as identifiers if + ** possible. Otherwise they remain as strings. Single-quoted + ** strings (ex: 'abc') are always string literals. + */ + case TK_STRING: { + if( pExpr->token.z[0]=='\'' ) break; + /* Fall thru into the TK_ID case if this is a double-quoted string */ + } + /* A lone identifier is the name of a column. + */ + case TK_ID: { + lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr); + return 1; + } + + /* A table name and column name: ID.ID + ** Or a database, table and column: ID.ID.ID + */ + case TK_DOT: { + Token *pColumn; + Token *pTable; + Token *pDb; + Expr *pRight; + + /* if( pSrcList==0 ) break; */ + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + pDb = 0; + pTable = &pExpr->pLeft->token; + pColumn = &pRight->token; + }else{ + assert( pRight->op==TK_DOT ); + pDb = &pExpr->pLeft->token; + pTable = &pRight->pLeft->token; + pColumn = &pRight->pRight->token; + } + lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); + return 1; + } + + /* Resolve function names + */ + case TK_CONST_FUNC: + case TK_FUNCTION: { + ExprList *pList = pExpr->pList; /* The argument list */ + int n = pList ? pList->nExpr : 0; /* Number of arguments */ + int no_such_func = 0; /* True if no such function exists */ + int wrong_num_args = 0; /* True if wrong number of arguments */ + int is_agg = 0; /* True if is an aggregate function */ + int i; + int auth; /* Authorization to use the function */ + int nId; /* Number of characters in function name */ + const char *zId; /* The function name. */ + FuncDef *pDef; /* Information about the function */ + int enc = ENC(pParse->db); /* The database encoding */ + + zId = (char*)pExpr->token.z; + nId = pExpr->token.n; + pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); + if( pDef==0 ){ + pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); + if( pDef==0 ){ + no_such_func = 1; + }else{ + wrong_num_args = 1; + } + }else{ + is_agg = pDef->xFunc==0; + } +#ifndef SQLITE_OMIT_AUTHORIZATION + if( pDef ){ + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); + if( auth!=SQLITE_OK ){ + if( auth==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; + } + pExpr->op = TK_NULL; + return 1; + } + } +#endif + if( is_agg && !pNC->allowAgg ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); + pNC->nErr++; + is_agg = 0; + }else if( no_such_func ){ + sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + pNC->nErr++; + }else if( wrong_num_args ){ + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", + nId, zId); + pNC->nErr++; + } + if( is_agg ){ + pExpr->op = TK_AGG_FUNCTION; + pNC->hasAgg = 1; + } + if( is_agg ) pNC->allowAgg = 0; + for(i=0; pNC->nErr==0 && ia[i].pExpr, nameResolverStep, pNC); + } + if( is_agg ) pNC->allowAgg = 1; + /* FIX ME: Compute pExpr->affinity based on the expected return + ** type of the function + */ + return is_agg; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: +#endif + case TK_IN: { + if( pExpr->pSelect ){ + int nRef = pNC->nRef; +#ifndef SQLITE_OMIT_CHECK + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); + } +#endif + sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); + assert( pNC->nRef>=nRef ); + if( nRef!=pNC->nRef ){ + ExprSetProperty(pExpr, EP_VarSelect); + } + } + break; + } +#ifndef SQLITE_OMIT_CHECK + case TK_VARIABLE: { + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); + } + break; + } +#endif + } + return 0; +} + +/* +** This routine walks an expression tree and resolves references to +** table columns. Nodes of the form ID.ID or ID resolve into an +** index to the table in the table list and a column offset. The +** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable +** value is changed to the index of the referenced table in pTabList +** plus the "base" value. The base value will ultimately become the +** VDBE cursor number for a cursor that is pointing into the referenced +** table. The Expr.iColumn value is changed to the index of the column +** of the referenced table. The Expr.iColumn value for the special +** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an +** alias for ROWID. +** +** Also resolve function names and check the functions for proper +** usage. Make sure all function names are recognized and all functions +** have the correct number of arguments. Leave an error message +** in pParse->zErrMsg if anything is amiss. Return the number of errors. +** +** If the expression contains aggregate functions then set the EP_Agg +** property on the expression. +*/ +int sqlite3ExprResolveNames( + NameContext *pNC, /* Namespace to resolve expressions in. */ + Expr *pExpr /* The expression to be analyzed. */ +){ + int savedHasAgg; + if( pExpr==0 ) return 0; +#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 + if( (pExpr->nHeight+pNC->pParse->nHeight)>SQLITE_MAX_EXPR_DEPTH ){ + sqlite3ErrorMsg(pNC->pParse, + "Expression tree is too large (maximum depth %d)", + SQLITE_MAX_EXPR_DEPTH + ); + return 1; + } + pNC->pParse->nHeight += pExpr->nHeight; +#endif + savedHasAgg = pNC->hasAgg; + pNC->hasAgg = 0; + walkExprTree(pExpr, nameResolverStep, pNC); +#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 + pNC->pParse->nHeight -= pExpr->nHeight; +#endif + if( pNC->nErr>0 ){ + ExprSetProperty(pExpr, EP_Error); + } + if( pNC->hasAgg ){ + ExprSetProperty(pExpr, EP_Agg); + }else if( savedHasAgg ){ + pNC->hasAgg = 1; + } + return ExprHasProperty(pExpr, EP_Error); +} + +/* +** A pointer instance of this structure is used to pass information +** through walkExprTree into codeSubqueryStep(). +*/ +typedef struct QueryCoder QueryCoder; +struct QueryCoder { + Parse *pParse; /* The parsing context */ + NameContext *pNC; /* Namespace of first enclosing query */ +}; + +#ifdef SQLITE_TEST + int sqlite3_enable_in_opt = 1; +#else + #define sqlite3_enable_in_opt 1 +#endif + +/* +** This function is used by the implementation of the IN (...) operator. +** It's job is to find or create a b-tree structure that may be used +** either to test for membership of the (...) set or to iterate through +** its members, skipping duplicates. +** +** The cursor opened on the structure (database table, database index +** or ephermal table) is stored in pX->iTable before this function returns. +** The returned value indicates the structure type, as follows: +** +** IN_INDEX_ROWID - The cursor was opened on a database table. +** IN_INDEX_INDEX - The cursor was opened on a database index. +** IN_INDEX_EPH - The cursor was opened on a specially created and +** populated epheremal table. +** +** An existing structure may only be used if the SELECT is of the simple +** form: +** +** SELECT FROM
+** +** If the mustBeUnique parameter is false, the structure will be used +** for fast set membership tests. In this case an epheremal table must +** be used unless is an INTEGER PRIMARY KEY or an index can +** be found with as its left-most column. +** +** If mustBeUnique is true, then the structure will be used to iterate +** through the set members, skipping any duplicates. In this case an +** epheremal table must be used unless the selected is guaranteed +** to be unique - either because it is an INTEGER PRIMARY KEY or it +** is unique by virtue of a constraint or implicit index. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){ + Select *p; + int eType = 0; + int iTab = pParse->nTab++; + + /* The follwing if(...) expression is true if the SELECT is of the + ** simple form: + ** + ** SELECT FROM
+ ** + ** If this is the case, it may be possible to use an existing table + ** or index instead of generating an epheremal table. + */ + if( sqlite3_enable_in_opt + && (p=pX->pSelect) && !p->pPrior + && !p->isDistinct && !p->isAgg && !p->pGroupBy + && p->pSrc && p->pSrc->nSrc==1 && !p->pSrc->a[0].pSelect + && !p->pSrc->a[0].pTab->pSelect + && p->pEList->nExpr==1 && p->pEList->a[0].pExpr->op==TK_COLUMN + && !p->pLimit && !p->pOffset && !p->pWhere + ){ + sqlite3 *db = pParse->db; + Index *pIdx; + Expr *pExpr = p->pEList->a[0].pExpr; + int iCol = pExpr->iColumn; + Vdbe *v = sqlite3GetVdbe(pParse); + + /* This function is only called from two places. In both cases the vdbe + ** has already been allocated. So assume sqlite3GetVdbe() is always + ** successful here. + */ + assert(v); + if( iCol<0 ){ + int iMem = ++pParse->nMem; + int iAddr; + Table *pTab = p->pSrc->a[0].pTab; + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3VdbeUsesBtree(v, iDb); + + iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); + + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + eType = IN_INDEX_ROWID; + + sqlite3VdbeJumpHere(v, iAddr); + }else{ + /* The collation sequence used by the comparison. If an index is to + ** be used in place of a temp-table, it must be ordered according + ** to this collation sequence. + */ + CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); + + /* Check that the affinity that will be used to perform the + ** comparison is the same as the affinity of the column. If + ** it is not, it is not possible to use any index. + */ + Table *pTab = p->pSrc->a[0].pTab; + char aff = comparisonAffinity(pX); + int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE); + + for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ + if( (pIdx->aiColumn[0]==iCol) + && (pReq==sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], -1, 0)) + && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) + ){ + int iDb; + int iMem = ++pParse->nMem; + int iAddr; + char *pKey; + + pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); + iDb = sqlite3SchemaToIndex(db, pIdx->pSchema); + sqlite3VdbeUsesBtree(v, iDb); + + iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); + + sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, + pKey,P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + eType = IN_INDEX_INDEX; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, iTab, pIdx->nColumn); + + sqlite3VdbeJumpHere(v, iAddr); + } + } + } + } + + if( eType==0 ){ + sqlite3CodeSubselect(pParse, pX); + eType = IN_INDEX_EPH; + }else{ + pX->iTable = iTab; + } + return eType; +} +#endif + +/* +** Generate code for scalar subqueries used as an expression +** and IN operators. Examples: +** +** (SELECT a FROM b) -- subquery +** EXISTS (SELECT a FROM b) -- EXISTS subquery +** x IN (4,5,11) -- IN operator with list on right-hand side +** x IN (SELECT a FROM b) -- IN operator with subquery on the right +** +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ + int testAddr = 0; /* One-time test address */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + + /* This code must be run in its entirety every time it is encountered + ** if any of the following is true: + ** + ** * The right-hand side is a correlated subquery + ** * The right-hand side is an expression list containing variables + ** * We are inside a trigger + ** + ** If all of the above are false, then we can run this code just once + ** save the results, and reuse the same result on subsequent invocations. + */ + if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ + int mem = ++pParse->nMem; + sqlite3VdbeAddOp1(v, OP_If, mem); + testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem); + assert( testAddr>0 || pParse->db->mallocFailed ); + } + + switch( pExpr->op ){ + case TK_IN: { + char affinity; + KeyInfo keyInfo; + int addr; /* Address of OP_OpenEphemeral instruction */ + + affinity = sqlite3ExprAffinity(pExpr->pLeft); + + /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' + ** expression it is handled the same way. A virtual table is + ** filled with single-field index keys representing the results + ** from the SELECT or the . + ** + ** If the 'x' expression is a column value, or the SELECT... + ** statement returns a column value, then the affinity of that + ** column is used to build the index keys. If both 'x' and the + ** SELECT... statement are columns, then numeric affinity is used + ** if either column has NUMERIC or INTEGER affinity. If neither + ** 'x' nor the SELECT... statement are columns, then numeric affinity + ** is used. + */ + pExpr->iTable = pParse->nTab++; + addr = sqlite3VdbeAddOp1(v, OP_OpenEphemeral, pExpr->iTable); + memset(&keyInfo, 0, sizeof(keyInfo)); + keyInfo.nField = 1; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, pExpr->iTable, 1); + + if( pExpr->pSelect ){ + /* Case 1: expr IN (SELECT ...) + ** + ** Generate code to write the results of the select into the temporary + ** table allocated and opened above. + */ + SelectDest dest; + ExprList *pEList; + + sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); + dest.affinity = (int)affinity; + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); + if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0, 0) ){ + return; + } + pEList = pExpr->pSelect->pEList; + if( pEList && pEList->nExpr>0 ){ + keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, + pEList->a[0].pExpr); + } + }else if( pExpr->pList ){ + /* Case 2: expr IN (exprlist) + ** + ** For each expression, build an index key from the evaluation and + ** store it in the temporary table. If is a column, then use + ** that columns affinity when building index keys. If is not + ** a column, use numeric affinity. + */ + int i; + ExprList *pList = pExpr->pList; + struct ExprList_item *pItem; + int r1, r2; + + if( !affinity ){ + affinity = SQLITE_AFF_NONE; + } + keyInfo.aColl[0] = pExpr->pLeft->pColl; + + /* Loop through each expression in . */ + r1 = sqlite3GetTempReg(pParse); + r2 = sqlite3GetTempReg(pParse); + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ + Expr *pE2 = pItem->pExpr; + + /* If the expression is not constant then we will need to + ** disable the test that was generated above that makes sure + ** this code only executes once. Because for a non-constant + ** expression we need to rerun this code each time. + */ + if( testAddr && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, testAddr-1, 2); + testAddr = 0; + } + + /* Evaluate the expression and insert it into the temp table */ + sqlite3ExprCode(pParse, pE2, r1); + sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + } + sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, r2); + } + sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); + break; + } + + case TK_EXISTS: + case TK_SELECT: { + /* This has to be a scalar SELECT. Generate code to put the + ** value of this select in a memory cell and record the number + ** of the memory cell in iColumn. + */ + static const Token one = { (u8*)"1", 0, 1 }; + Select *pSel; + SelectDest dest; + + pSel = pExpr->pSelect; + sqlite3SelectDestInit(&dest, 0, ++pParse->nMem); + if( pExpr->op==TK_SELECT ){ + dest.eDest = SRT_Mem; + sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iParm); + VdbeComment((v, "Init subquery result")); + }else{ + dest.eDest = SRT_Exists; + sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm); + VdbeComment((v, "Init EXISTS result")); + } + sqlite3ExprDelete(pSel->pLimit); + pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); + if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0, 0) ){ + return; + } + pExpr->iColumn = dest.iParm; + break; + } + } + + if( testAddr ){ + sqlite3VdbeJumpHere(v, testAddr-1); + } + + return; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +/* +** Duplicate an 8-byte value +*/ +static char *dup8bytes(Vdbe *v, const char *in){ + char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8); + if( out ){ + memcpy(out, in, 8); + } + return out; +} + +/* +** Generate an instruction that will put the floating point +** value described by z[0..n-1] into register iMem. +** +** The z[] string will probably not be zero-terminated. But the +** z[n] character is guaranteed to be something that does not look +** like the continuation of the number. +*/ +static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){ + assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); + if( z ){ + double value; + char *zV; + assert( !isdigit(z[n]) ); + sqlite3AtoF(z, &value); + if( negateFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); + } +} + + +/* +** Generate an instruction that will put the integer describe by +** text z[0..n-1] into register iMem. +** +** The z[] string will probably not be zero-terminated. But the +** z[n] character is guaranteed to be something that does not look +** like the continuation of the number. +*/ +static void codeInteger(Vdbe *v, const char *z, int n, int negFlag, int iMem){ + assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed ); + if( z ){ + int i; + assert( !isdigit(z[n]) ); + if( sqlite3GetInt32(z, &i) ){ + if( negFlag ) i = -i; + sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); + }else if( sqlite3FitsIn64Bits(z, negFlag) ){ + i64 value; + char *zV; + sqlite3Atoi64(z, &value); + if( negFlag ) value = -value; + zV = dup8bytes(v, (char*)&value); + sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); + }else{ + codeReal(v, z, n, negFlag, iMem); + } + } +} + + +/* +** Generate code that will extract the iColumn-th column from +** table pTab and store the column value in register iReg. +** There is an open cursor to pTab in +** iTable. If iColumn<0 then code is generated that extracts the rowid. +*/ +void sqlite3ExprCodeGetColumn( + Vdbe *v, /* The VM being created */ + Table *pTab, /* Description of the table we are reading from */ + int iColumn, /* Index of the table column */ + int iTable, /* The cursor pointing to the table */ + int iReg /* Store results here */ +){ + if( iColumn<0 ){ + int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; + sqlite3VdbeAddOp2(v, op, iTable, iReg); + }else if( pTab==0 ){ + sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg); + }else{ + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; + sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg); + sqlite3ColumnDefault(v, pTab, iColumn); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg); + } +#endif + } +} + +/* +** Generate code into the current Vdbe to evaluate the given +** expression. Attempt to store the results in register "target". +** Return the register where results are stored. +** +** With this routine, there is no guaranteed that results will +** be stored in target. The result might be stored in some other +** register if it is convenient to do so. The calling function +** must check the return code and move the results to the desired +** register. +*/ +static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; /* The VM under construction */ + int op; /* The opcode being coded */ + int inReg = target; /* Results stored in register inReg */ + int regFree1 = 0; /* If non-zero free this temporary register */ + int regFree2 = 0; /* If non-zero free this temporary register */ + int r1, r2, r3; /* Various register numbers */ + + assert( v!=0 || pParse->db->mallocFailed ); + assert( target>0 && target<=pParse->nMem ); + if( v==0 ) return 0; + + if( pExpr==0 ){ + op = TK_NULL; + }else{ + op = pExpr->op; + } + switch( op ){ + case TK_AGG_COLUMN: { + AggInfo *pAggInfo = pExpr->pAggInfo; + struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; + if( !pAggInfo->directMode ){ + assert( pCol->iMem>0 ); + inReg = pCol->iMem; + break; + }else if( pAggInfo->useSortingIdx ){ + sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx, + pCol->iSorterColumn, target); + break; + } + /* Otherwise, fall thru into the TK_COLUMN case */ + } + case TK_COLUMN: { + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + assert( pParse->ckBase>0 ); + inReg = pExpr->iColumn + pParse->ckBase; + }else{ + sqlite3ExprCodeGetColumn(v, pExpr->pTab, + pExpr->iColumn, pExpr->iTable, target); + } + break; + } + case TK_INTEGER: { + codeInteger(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); + break; + } + case TK_FLOAT: { + codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); + break; + } + case TK_STRING: { + sqlite3DequoteExpr(pParse->db, pExpr); + sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0, + (char*)pExpr->token.z, pExpr->token.n); + break; + } + case TK_NULL: { + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + break; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + int n; + const char *z; + char *zBlob; + assert( pExpr->token.n>=3 ); + assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' ); + assert( pExpr->token.z[1]=='\'' ); + assert( pExpr->token.z[pExpr->token.n-1]=='\'' ); + n = pExpr->token.n - 3; + z = (char*)pExpr->token.z + 2; + zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); + sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC); + break; + } +#endif + case TK_VARIABLE: { + sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iTable, target); + if( pExpr->token.n>1 ){ + sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n); + } + break; + } + case TK_REGISTER: { + inReg = pExpr->iTable; + break; + } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + int aff, to_op; + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + aff = sqlite3AffinityType(&pExpr->token); + to_op = aff - SQLITE_AFF_TEXT + OP_ToText; + assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); + assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); + assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); + assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); + assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); + sqlite3VdbeAddOp1(v, to_op, inReg); + break; + } +#endif /* SQLITE_OMIT_CAST */ + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, inReg, SQLITE_STOREP2); + break; + } + case TK_AND: + case TK_OR: + case TK_PLUS: + case TK_STAR: + case TK_MINUS: + case TK_REM: + case TK_BITAND: + case TK_BITOR: + case TK_SLASH: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: { + assert( TK_AND==OP_And ); + assert( TK_OR==OP_Or ); + assert( TK_PLUS==OP_Add ); + assert( TK_MINUS==OP_Subtract ); + assert( TK_REM==OP_Remainder ); + assert( TK_BITAND==OP_BitAnd ); + assert( TK_BITOR==OP_BitOr ); + assert( TK_SLASH==OP_Divide ); + assert( TK_LSHIFT==OP_ShiftLeft ); + assert( TK_RSHIFT==OP_ShiftRight ); + assert( TK_CONCAT==OP_Concat ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + sqlite3VdbeAddOp3(v, op, r2, r1, target); + break; + } + case TK_UMINUS: { + Expr *pLeft = pExpr->pLeft; + assert( pLeft ); + if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ + Token *p = &pLeft->token; + if( pLeft->op==TK_FLOAT ){ + codeReal(v, (char*)p->z, p->n, 1, target); + }else{ + codeInteger(v, (char*)p->z, p->n, 1, target); + } + }else{ + regFree1 = r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); + r2 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); + } + inReg = target; + break; + } + case TK_BITNOT: + case TK_NOT: { + assert( TK_BITNOT==OP_BitNot ); + assert( TK_NOT==OP_Not ); + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + sqlite3VdbeAddOp1(v, op, inReg); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + int addr; + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + addr = sqlite3VdbeAddOp1(v, op, r1); + sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); + sqlite3VdbeJumpHere(v, addr); + break; + } + case TK_AGG_FUNCTION: { + AggInfo *pInfo = pExpr->pAggInfo; + if( pInfo==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", + &pExpr->span); + }else{ + inReg = pInfo->aFunc[pExpr->iAgg].iMem; + } + break; + } + case TK_CONST_FUNC: + case TK_FUNCTION: { + ExprList *pList = pExpr->pList; + int nExpr = pList ? pList->nExpr : 0; + FuncDef *pDef; + int nId; + const char *zId; + int constMask = 0; + int i; + sqlite3 *db = pParse->db; + u8 enc = ENC(db); + CollSeq *pColl = 0; + + zId = (char*)pExpr->token.z; + nId = pExpr->token.n; + pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); + assert( pDef!=0 ); + if( pList ){ + nExpr = pList->nExpr; + r1 = sqlite3GetTempRange(pParse, nExpr); + sqlite3ExprCodeExprList(pParse, pList, r1); + }else{ + nExpr = r1 = 0; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Possibly overload the function if the first argument is + ** a virtual table column. + ** + ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the + ** second argument, not the first, as the argument to test to + ** see if it is a column in a virtual table. This is done because + ** the left operand of infix functions (the operand we want to + ** control overloading) ends up as the second argument to the + ** function. The expression "A glob B" is equivalent to + ** "glob(B,A). We want to use the A in "A glob B" to test + ** for function overloading. But we use the B term in "glob(B,A)". + */ + if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[1].pExpr); + }else if( nExpr>0 ){ + pDef = sqlite3VtabOverloadFunction(db, pDef, nExpr, pList->a[0].pExpr); + } +#endif + for(i=0; ia[i].pExpr) ){ + constMask |= (1<needCollSeq && !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); + } + } + if( pDef->needCollSeq ){ + if( !pColl ) pColl = pParse->db->pDfltColl; + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + } + sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, + (char*)pDef, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, nExpr); + if( nExpr ){ + sqlite3ReleaseTempRange(pParse, r1, nExpr); + } + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: + case TK_SELECT: { + if( pExpr->iColumn==0 ){ + sqlite3CodeSubselect(pParse, pExpr); + } + inReg = pExpr->iColumn; + break; + } + case TK_IN: { + int j1, j2, j3, j4, j5; + char affinity; + int eType; + + eType = sqlite3FindInIndex(pParse, pExpr, 0); + + /* Figure out the affinity to use to create a key from the results + ** of the expression. affinityStr stores a static string suitable for + ** P4 of OP_MakeRecord. + */ + affinity = comparisonAffinity(pExpr); + + sqlite3VdbeAddOp2(v, OP_Integer, 1, target); + + /* Code the from " IN (...)". The temporary table + ** pExpr->iTable contains the values that make up the (...) set. + */ + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + j2 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j1); + if( eType==IN_INDEX_ROWID ){ + j3 = sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, 0, 1); + j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1); + j5 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j3); + sqlite3VdbeJumpHere(v, j4); + }else{ + r2 = regFree2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); + j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2); + } + sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeJumpHere(v, j5); + break; + } +#endif + /* + ** x BETWEEN y AND z + ** + ** This is equivalent to + ** + ** x>=y AND x<=z + ** + ** X is stored in pExpr->pLeft. + ** Y is stored in pExpr->pList->a[0].pExpr. + ** Z is stored in pExpr->pList->a[1].pExpr. + */ + case TK_BETWEEN: { + Expr *pLeft = pExpr->pLeft; + struct ExprList_item *pLItem = pExpr->pList->a; + Expr *pRight = pLItem->pExpr; + + r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); + r3 = sqlite3GetTempReg(pParse); + codeCompare(pParse, pLeft, pRight, OP_Ge, + r1, r2, r3, SQLITE_STOREP2); + pLItem++; + pRight = pLItem->pExpr; + sqlite3ReleaseTempReg(pParse, regFree2); + r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2); + codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r2, SQLITE_STOREP2); + sqlite3VdbeAddOp3(v, OP_And, r3, r2, target); + sqlite3ReleaseTempReg(pParse, r3); + break; + } + case TK_UPLUS: { + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + break; + } + + /* + ** Form A: + ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END + ** + ** Form B: + ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END + ** + ** Form A is can be transformed into the equivalent form B as follows: + ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ... + ** WHEN x=eN THEN rN ELSE y END + ** + ** X (if it exists) is in pExpr->pLeft. + ** Y is in pExpr->pRight. The Y is also optional. If there is no + ** ELSE clause and no other term matches, then the result of the + ** exprssion is NULL. + ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1]. + ** + ** The result of the expression is the Ri for the first matching Ei, + ** or if there is no matching Ei, the ELSE term Y, or if there is + ** no ELSE term, NULL. + */ + case TK_CASE: { + int endLabel; /* GOTO label for end of CASE stmt */ + int nextCase; /* GOTO label for next WHEN clause */ + int nExpr; /* 2x number of WHEN terms */ + int i; /* Loop counter */ + ExprList *pEList; /* List of WHEN terms */ + struct ExprList_item *aListelem; /* Array of WHEN terms */ + Expr opCompare; /* The X==Ei expression */ + Expr cacheX; /* Cached expression X */ + Expr *pX; /* The X expression */ + Expr *pTest; /* X==Ei (form A) or just Ei (form B) */ + + assert(pExpr->pList); + assert((pExpr->pList->nExpr % 2) == 0); + assert(pExpr->pList->nExpr > 0); + pEList = pExpr->pList; + aListelem = pEList->a; + nExpr = pEList->nExpr; + endLabel = sqlite3VdbeMakeLabel(v); + if( (pX = pExpr->pLeft)!=0 ){ + cacheX = *pX; + cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1); + cacheX.op = TK_REGISTER; + opCompare.op = TK_EQ; + opCompare.pLeft = &cacheX; + pTest = &opCompare; + } + for(i=0; ipRight ){ + sqlite3ExprCode(pParse, pExpr->pRight, target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + sqlite3VdbeResolveLabel(v, endLabel); + break; + } +#ifndef SQLITE_OMIT_TRIGGER + case TK_RAISE: { + if( !pParse->trigStack ){ + sqlite3ErrorMsg(pParse, + "RAISE() may only be used within a trigger-program"); + return 0; + } + if( pExpr->iColumn!=OE_Ignore ){ + assert( pExpr->iColumn==OE_Rollback || + pExpr->iColumn == OE_Abort || + pExpr->iColumn == OE_Fail ); + sqlite3DequoteExpr(pParse->db, pExpr); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0, + (char*)pExpr->token.z, pExpr->token.n); + } else { + assert( pExpr->iColumn == OE_Ignore ); + sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); + sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump); + VdbeComment((v, "raise(IGNORE)")); + } + break; + } +#endif + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); + return inReg; +} + +/* +** Generate code to evaluate an expression and store the results +** into a register. Return the register number where the results +** are stored. +** +** If the register is a temporary register that can be deallocated, +** then write its number into *pReg. If the result register is no +** a temporary, then set *pReg to zero. +*/ +int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ + int r1 = sqlite3GetTempReg(pParse); + int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); + if( r2==r1 ){ + *pReg = r1; + }else{ + sqlite3ReleaseTempReg(pParse, r1); + *pReg = 0; + } + return r2; +} + +/* +** Generate code that will evaluate expression pExpr and store the +** results in register target. The results are guaranteed to appear +** in register target. +*/ +int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ + int inReg; + + assert( target>0 && target<=pParse->nMem ); + inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + assert( pParse->pVdbe || pParse->db->mallocFailed ); + if( inReg!=target && pParse->pVdbe ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); + } + return target; +} + +/* +** Generate code that evalutes the given expression and puts the result +** in register target. +** +** Also make a copy of the expression results into another "cache" register +** and modify the expression so that the next time it is evaluated, +** the result is a copy of the cache register. +** +** This routine is used for expressions that are used multiple +** times. They are evaluated once and the results of the expression +** are reused. +*/ +int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ + Vdbe *v = pParse->pVdbe; + int inReg; + inReg = sqlite3ExprCode(pParse, pExpr, target); + assert( target>0 ); + if( pExpr->op!=TK_REGISTER ){ + int iMem; + iMem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem); + pExpr->iTable = iMem; + pExpr->op = TK_REGISTER; + } + return inReg; +} + + +/* +** Generate code that pushes the value of every element of the given +** expression list into a sequence of registers beginning at target. +** +** Return the number of elements evaluated. +*/ +int sqlite3ExprCodeExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* The expression list to be coded */ + int target /* Where to write results */ +){ + struct ExprList_item *pItem; + int i, n; + assert( pList!=0 || pParse->db->mallocFailed ); + if( pList==0 ){ + return 0; + } + assert( target>0 ); + n = pList->nExpr; + for(pItem=pList->a, i=n; i>0; i--, pItem++){ + sqlite3ExprCode(pParse, pItem->pExpr, target); + target++; + } + return n; +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is true but execution +** continues straight thru if the expression is false. +** +** If the expression evaluates to NULL (neither true nor false), then +** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. +*/ +void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int regFree1 = 0; + int regFree2 = 0; + int r1, r2; + + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); + if( v==0 || pExpr==0 ) return; + op = pExpr->op; + switch( op ){ + case TK_AND: { + int d2 = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + break; + } + case TK_OR: { + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + break; + } + case TK_NOT: { + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, jumpIfNull); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeAddOp2(v, op, r1, dest); + break; + } + case TK_BETWEEN: { + /* x BETWEEN y AND z + ** + ** Is equivalent to + ** + ** x>=y AND x<=z + ** + ** Code it as such, taking care to do the common subexpression + ** elementation of x. + */ + Expr exprAnd; + Expr compLeft; + Expr compRight; + Expr exprX; + + exprX = *pExpr->pLeft; + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = &exprX; + compLeft.pRight = pExpr->pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = &exprX; + compRight.pRight = pExpr->pList->a[1].pExpr; + exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); + exprX.op = TK_REGISTER; + sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull); + break; + } + default: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0); + break; + } + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is false but execution +** continues straight thru if the expression is true. +** +** If the expression evaluates to NULL (neither true nor false) then +** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull +** is 0. +*/ +void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int regFree1 = 0; + int regFree2 = 0; + int r1, r2; + + assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 ); + if( v==0 || pExpr==0 ) return; + + /* The value of pExpr->op and op are related as follows: + ** + ** pExpr->op op + ** --------- ---------- + ** TK_ISNULL OP_NotNull + ** TK_NOTNULL OP_IsNull + ** TK_NE OP_Eq + ** TK_EQ OP_Ne + ** TK_GT OP_Le + ** TK_LE OP_Gt + ** TK_GE OP_Lt + ** TK_LT OP_Ge + ** + ** For other values of pExpr->op, op is undefined and unused. + ** The value of TK_ and OP_ constants are arranged such that we + ** can compute the mapping above using the following expression. + ** Assert()s verify that the computation is correct. + */ + op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); + + /* Verify correct alignment of TK_ and OP_ constants + */ + assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); + assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); + assert( pExpr->op!=TK_NE || op==OP_Eq ); + assert( pExpr->op!=TK_EQ || op==OP_Ne ); + assert( pExpr->op!=TK_LT || op==OP_Ge ); + assert( pExpr->op!=TK_LE || op==OP_Gt ); + assert( pExpr->op!=TK_GT || op==OP_Le ); + assert( pExpr->op!=TK_GE || op==OP_Lt ); + + switch( pExpr->op ){ + case TK_AND: { + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + break; + } + case TK_OR: { + int d2 = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + break; + } + case TK_NOT: { + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, + r1, r2, dest, jumpIfNull); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeAddOp2(v, op, r1, dest); + break; + } + case TK_BETWEEN: { + /* x BETWEEN y AND z + ** + ** Is equivalent to + ** + ** x>=y AND x<=z + ** + ** Code it as such, taking care to do the common subexpression + ** elementation of x. + */ + Expr exprAnd; + Expr compLeft; + Expr compRight; + Expr exprX; + + exprX = *pExpr->pLeft; + exprAnd.op = TK_AND; + exprAnd.pLeft = &compLeft; + exprAnd.pRight = &compRight; + compLeft.op = TK_GE; + compLeft.pLeft = &exprX; + compLeft.pRight = pExpr->pList->a[0].pExpr; + compRight.op = TK_LE; + compRight.pLeft = &exprX; + compRight.pRight = pExpr->pList->a[1].pExpr; + exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, ®Free1); + exprX.op = TK_REGISTER; + sqlite3ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull); + break; + } + default: { + r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1); + sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0); + break; + } + } + sqlite3ReleaseTempReg(pParse, regFree1); + sqlite3ReleaseTempReg(pParse, regFree2); +} + +/* +** Do a deep comparison of two expression trees. Return TRUE (non-zero) +** if they are identical and return FALSE if they differ in any way. +** +** Sometimes this routine will return FALSE even if the two expressions +** really are equivalent. If we cannot prove that the expressions are +** identical, we return FALSE just to be safe. So if this routine +** returns false, then you do not really know for certain if the two +** expressions are the same. But if you get a TRUE return, then you +** can be sure the expressions are the same. In the places where +** this routine is used, it does not hurt to get an extra FALSE - that +** just might result in some slightly slower code. But returning +** an incorrect TRUE could lead to a malfunction. +*/ +int sqlite3ExprCompare(Expr *pA, Expr *pB){ + int i; + if( pA==0||pB==0 ){ + return pB==pA; + } + if( pA->op!=pB->op ) return 0; + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; + if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; + if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; + if( pA->pList ){ + if( pB->pList==0 ) return 0; + if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; + for(i=0; ipList->nExpr; i++){ + if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ + return 0; + } + } + }else if( pB->pList ){ + return 0; + } + if( pA->pSelect || pB->pSelect ) return 0; + if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; + if( pA->op!=TK_COLUMN && pA->token.z ){ + if( pB->token.z==0 ) return 0; + if( pB->token.n!=pA->token.n ) return 0; + if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + return 0; + } + } + return 1; +} + + +/* +** Add a new element to the pAggInfo->aCol[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ + int i; + pInfo->aCol = sqlite3ArrayAllocate( + db, + pInfo->aCol, + sizeof(pInfo->aCol[0]), + 3, + &pInfo->nColumn, + &pInfo->nColumnAlloc, + &i + ); + return i; +} + +/* +** Add a new element to the pAggInfo->aFunc[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ + int i; + pInfo->aFunc = sqlite3ArrayAllocate( + db, + pInfo->aFunc, + sizeof(pInfo->aFunc[0]), + 3, + &pInfo->nFunc, + &pInfo->nFuncAlloc, + &i + ); + return i; +} + +/* +** This is an xFunc for walkExprTree() used to implement +** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates +** for additional information. +** +** This routine analyzes the aggregate function at pExpr. +*/ +static int analyzeAggregate(void *pArg, Expr *pExpr){ + int i; + NameContext *pNC = (NameContext *)pArg; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; + AggInfo *pAggInfo = pNC->pAggInfo; + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + /* Check to see if the column is in one of the tables in the FROM + ** clause of the aggregate query */ + if( pSrcList ){ + struct SrcList_item *pItem = pSrcList->a; + for(i=0; inSrc; i++, pItem++){ + struct AggInfo_col *pCol; + if( pExpr->iTable==pItem->iCursor ){ + /* If we reach this point, it means that pExpr refers to a table + ** that is in the FROM clause of the aggregate query. + ** + ** Make an entry for the column in pAggInfo->aCol[] if there + ** is not an entry there already. + */ + int k; + pCol = pAggInfo->aCol; + for(k=0; knColumn; k++, pCol++){ + if( pCol->iTable==pExpr->iTable && + pCol->iColumn==pExpr->iColumn ){ + break; + } + } + if( (k>=pAggInfo->nColumn) + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = ++pParse->nMem; + pCol->iSorterColumn = -1; + pCol->pExpr = pExpr; + if( pAggInfo->pGroupBy ){ + int j, n; + ExprList *pGB = pAggInfo->pGroupBy; + struct ExprList_item *pTerm = pGB->a; + n = pGB->nExpr; + for(j=0; jpExpr; + if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && + pE->iColumn==pExpr->iColumn ){ + pCol->iSorterColumn = j; + break; + } + } + } + if( pCol->iSorterColumn<0 ){ + pCol->iSorterColumn = pAggInfo->nSortingColumn++; + } + } + /* There is now an entry for pExpr in pAggInfo->aCol[] (either + ** because it was there before or because we just created it). + ** Convert the pExpr to be a TK_AGG_COLUMN referring to that + ** pAggInfo->aCol[] entry. + */ + pExpr->pAggInfo = pAggInfo; + pExpr->op = TK_AGG_COLUMN; + pExpr->iAgg = k; + break; + } /* endif pExpr->iTable==pItem->iCursor */ + } /* end loop over pSrcList */ + } + return 1; + } + case TK_AGG_FUNCTION: { + /* The pNC->nDepth==0 test causes aggregate functions in subqueries + ** to be ignored */ + if( pNC->nDepth==0 ){ + /* Check to see if pExpr is a duplicate of another aggregate + ** function that is already in the pAggInfo structure + */ + struct AggInfo_func *pItem = pAggInfo->aFunc; + for(i=0; inFunc; i++, pItem++){ + if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ + break; + } + } + if( i>=pAggInfo->nFunc ){ + /* pExpr is original. Make a new entry in pAggInfo->aFunc[] + */ + u8 enc = ENC(pParse->db); + i = addAggInfoFunc(pParse->db, pAggInfo); + if( i>=0 ){ + pItem = &pAggInfo->aFunc[i]; + pItem->pExpr = pExpr; + pItem->iMem = ++pParse->nMem; + pItem->pFunc = sqlite3FindFunction(pParse->db, + (char*)pExpr->token.z, pExpr->token.n, + pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); + if( pExpr->flags & EP_Distinct ){ + pItem->iDistinct = pParse->nTab++; + }else{ + pItem->iDistinct = -1; + } + } + } + /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry + */ + pExpr->iAgg = i; + pExpr->pAggInfo = pAggInfo; + return 1; + } + } + } + + /* Recursively walk subqueries looking for TK_COLUMN nodes that need + ** to be changed to TK_AGG_COLUMN. But increment nDepth so that + ** TK_AGG_FUNCTION nodes in subqueries will be unchanged. + */ + if( pExpr->pSelect ){ + pNC->nDepth++; + walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); + pNC->nDepth--; + } + return 0; +} + +/* +** Analyze the given expression looking for aggregate functions and +** for variables that need to be added to the pParse->aAgg[] array. +** Make additional entries to the pParse->aAgg[] array as necessary. +** +** This routine should only be called after the expression has been +** analyzed by sqlite3ExprResolveNames(). +*/ +void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ + walkExprTree(pExpr, analyzeAggregate, pNC); +} + +/* +** Call sqlite3ExprAnalyzeAggregates() for every expression in an +** expression list. Return the number of errors. +** +** If an error is found, the analysis is cut short. +*/ +void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ + struct ExprList_item *pItem; + int i; + if( pList ){ + for(pItem=pList->a, i=0; inExpr; i++, pItem++){ + sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); + } + } +} + +/* +** Allocate or deallocate temporary use registers during code generation. +*/ +int sqlite3GetTempReg(Parse *pParse){ + if( pParse->nTempReg ){ + return pParse->aTempReg[--pParse->nTempReg]; + }else{ + return ++pParse->nMem; + } +} +void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ + if( iReg && pParse->nTempRegaTempReg) ){ + assert( iReg>0 ); + pParse->aTempReg[pParse->nTempReg++] = iReg; + } +} + +/* +** Allocate or deallocate a block of nReg consecutive registers +*/ +int sqlite3GetTempRange(Parse *pParse, int nReg){ + int i; + if( nReg<=pParse->nRangeReg ){ + i = pParse->iRangeReg; + pParse->iRangeReg += nReg; + pParse->nRangeReg -= nReg; + }else{ + i = pParse->nMem+1; + pParse->nMem += nReg; + } + return i; +} +void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ + if( nReg>pParse->nRangeReg ){ + pParse->nRangeReg = nReg; + pParse->iRangeReg = iReg; + } +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/fault.c b/client/src/thirdparty/sqlite-3.4.2/src/fault.c new file mode 100644 index 0000000..4cc369e --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/fault.c @@ -0,0 +1,147 @@ +/* +** 2008 Jan 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 to implement a fault-injector used for +** testing and verification of SQLite. +** +** Subsystems within SQLite can call sqlite3FaultStep() to see if +** they should simulate a fault. sqlite3FaultStep() normally returns +** zero but will return non-zero if a fault should be simulated. +** Fault injectors can be used, for example, to simulate memory +** allocation failures or I/O errors. +** +** The fault injector is omitted from the code if SQLite is +** compiled with -DSQLITE_OMIT_FAULTINJECTOR=1. There is a very +** small performance hit for leaving the fault injector in the code. +** Commerical products will probably want to omit the fault injector +** from production builds. But safety-critical systems who work +** under the motto "fly what you test and test what you fly" may +** choose to leave the fault injector enabled even in production. +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_FAULTINJECTOR + +/* +** There can be various kinds of faults. For example, there can be +** a memory allocation failure. Or an I/O failure. For each different +** fault type, there is a separate FaultInjector structure to keep track +** of the status of that fault. +*/ +static struct FaultInjector { + int iCountdown; /* Number of pending successes before we hit a failure */ + int nRepeat; /* Number of times to repeat the failure */ + int nBenign; /* Number of benign failures seen since last config */ + int nFail; /* Number of failures seen since last config */ + u8 enable; /* True if enabled */ + u8 benign; /* Ture if next failure will be benign */ +} aFault[SQLITE_FAULTINJECTOR_COUNT]; + +/* +** This routine configures and enables a fault injector. After +** calling this routine, aFaultStep() will return false (zero) +** nDelay times, then it will return true nRepeat times, +** then it will again begin returning false. +*/ +void sqlite3FaultConfig(int id, int nDelay, int nRepeat){ + assert( id>=0 && id=0; + aFault[id].benign = 0; +} + +/* +** Return the number of faults (both hard and benign faults) that have +** occurred since the injector was last configured. +*/ +int sqlite3FaultFailures(int id){ + assert( id>=0 && id=0 && id=0 && id=0 && id=0 && id0 ){ + aFault[id].iCountdown--; + return 0; + } + sqlite3Fault(); + aFault[id].nFail++; + if( aFault[id].benign ){ + aFault[id].nBenign++; + } + aFault[id].nRepeat--; + if( aFault[id].nRepeat<=0 ){ + aFault[id].enable = 0; + } + return 1; +} + +#endif /* SQLITE_OMIT_FAULTINJECTOR */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/func.c b/client/src/thirdparty/sqlite-3.4.2/src/func.c new file mode 100644 index 0000000..840254b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/func.c @@ -0,0 +1,1572 @@ +/* +** 2002 February 23 +** +** 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 the C functions that implement various SQL +** functions of SQLite. +** +** There is only one exported symbol in this file - the function +** sqliteRegisterBuildinFunctions() found at the bottom of the file. +** All other code has file scope. +** +** $Id: func.c,v 1.183 2008/01/21 16:22:46 drh Exp $ +*/ +#include "sqliteInt.h" +#include +#include +#include +#include "vdbeInt.h" + + +/* +** Return the collating function associated with a function. +*/ +static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ + return context->pColl; +} + +/* +** Implementation of the non-aggregate min() and max() functions +*/ +static void minmaxFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + int mask; /* 0 for min() or 0xffffffff for max() */ + int iBest; + CollSeq *pColl; + + if( argc==0 ) return; + mask = sqlite3_user_data(context)==0 ? 0 : -1; + pColl = sqlite3GetFuncCollSeq(context); + assert( pColl ); + assert( mask==-1 || mask==0 ); + iBest = 0; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + for(i=1; i=0 ){ + iBest = i; + } + } + sqlite3_result_value(context, argv[iBest]); +} + +/* +** Return the type of the argument. +*/ +static void typeofFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *z = 0; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: z = "null"; break; + case SQLITE_INTEGER: z = "integer"; break; + case SQLITE_TEXT: z = "text"; break; + case SQLITE_FLOAT: z = "real"; break; + case SQLITE_BLOB: z = "blob"; break; + } + sqlite3_result_text(context, z, -1, SQLITE_STATIC); +} + + +/* +** Implementation of the length() function +*/ +static void lengthFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int len; + + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_BLOB: + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); + break; + } + case SQLITE_TEXT: { + const unsigned char *z = sqlite3_value_text(argv[0]); + if( z==0 ) return; + len = 0; + while( *z ){ + len++; + SQLITE_SKIP_UTF8(z); + } + sqlite3_result_int(context, len); + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + +/* +** Implementation of the abs() function +*/ +static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + if( iVal<0 ){ + if( (iVal<<1)==0 ){ + sqlite3_result_error(context, "integer overflow", -1); + return; + } + iVal = -iVal; + } + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + double rVal = sqlite3_value_double(argv[0]); + if( rVal<0 ) rVal = -rVal; + sqlite3_result_double(context, rVal); + break; + } + } +} + +/* +** Implementation of the substr() function. +** +** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. +** p1 is 1-indexed. So substr(x,1,1) returns the first character +** of x. If x is text, then we actually count UTF-8 characters. +** If x is a blob, then we count bytes. +** +** If p1 is negative, then we begin abs(p1) from the end of x[]. +*/ +static void substrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *z; + const unsigned char *z2; + int len; + int p0type; + i64 p1, p2; + + assert( argc==3 || argc==2 ); + p0type = sqlite3_value_type(argv[0]); + if( p0type==SQLITE_BLOB ){ + len = sqlite3_value_bytes(argv[0]); + z = sqlite3_value_blob(argv[0]); + if( z==0 ) return; + assert( len==sqlite3_value_bytes(argv[0]) ); + }else{ + z = sqlite3_value_text(argv[0]); + if( z==0 ) return; + len = 0; + for(z2=z; *z2; len++){ + SQLITE_SKIP_UTF8(z2); + } + } + p1 = sqlite3_value_int(argv[1]); + if( argc==3 ){ + p2 = sqlite3_value_int(argv[2]); + }else{ + p2 = SQLITE_MAX_LENGTH; + } + if( p1<0 ){ + p1 += len; + if( p1<0 ){ + p2 += p1; + p1 = 0; + } + }else if( p1>0 ){ + p1--; + } + if( p1+p2>len ){ + p2 = len-p1; + } + if( p0type!=SQLITE_BLOB ){ + while( *z && p1 ){ + SQLITE_SKIP_UTF8(z); + p1--; + } + for(z2=z; *z2 && p2; p2--){ + SQLITE_SKIP_UTF8(z2); + } + sqlite3_result_text(context, (char*)z, z2-z, SQLITE_TRANSIENT); + }else{ + if( p2<0 ) p2 = 0; + sqlite3_result_blob(context, (char*)&z[p1], p2, SQLITE_TRANSIENT); + } +} + +/* +** Implementation of the round() function +*/ +static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + int n = 0; + double r; + char zBuf[500]; /* larger than the %f representation of the largest double */ + assert( argc==1 || argc==2 ); + if( argc==2 ){ + if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; + n = sqlite3_value_int(argv[1]); + if( n>30 ) n = 30; + if( n<0 ) n = 0; + } + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + r = sqlite3_value_double(argv[0]); + sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r); + sqlite3AtoF(zBuf, &r); + sqlite3_result_double(context, r); +} + +/* +** Allocate nByte bytes of space using sqlite3_malloc(). If the +** allocation fails, call sqlite3_result_error_nomem() to notify +** the database handle that malloc() has failed. +*/ +static void *contextMalloc(sqlite3_context *context, int nByte){ + char *z = sqlite3_malloc(nByte); + if( !z && nByte>0 ){ + sqlite3_result_error_nomem(context); + } + return z; +} + +/* +** Implementation of the upper() and lower() SQL functions. +*/ +static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char *z1; + const char *z2; + int i, n; + if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + z1 = contextMalloc(context, n+1); + if( z1 ){ + memcpy(z1, z2, n+1); + for(i=0; z1[i]; i++){ + z1[i] = toupper(z1[i]); + } + sqlite3_result_text(context, z1, -1, sqlite3_free); + } + } +} +static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char *z1; + const char *z2; + int i, n; + if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + z1 = contextMalloc(context, n+1); + if( z1 ){ + memcpy(z1, z2, n+1); + for(i=0; z1[i]; i++){ + z1[i] = tolower(z1[i]); + } + sqlite3_result_text(context, z1, -1, sqlite3_free); + } + } +} + +/* +** Implementation of the IFNULL(), NVL(), and COALESCE() functions. +** All three do the same thing. They return the first non-NULL +** argument. +*/ +static void ifnullFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + for(i=0; iSQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + p = contextMalloc(context, n); + if( p ){ + sqlite3Randomness(n, p); + sqlite3_result_blob(context, (char*)p, n, sqlite3_free); + } +} + +/* +** Implementation of the last_insert_rowid() SQL function. The return +** value is the same as the sqlite3_last_insert_rowid() API function. +*/ +static void last_insert_rowid( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_user_data(context); + sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); +} + +/* +** Implementation of the changes() SQL function. The return value is the +** same as the sqlite3_changes() API function. +*/ +static void changes( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_user_data(context); + sqlite3_result_int(context, sqlite3_changes(db)); +} + +/* +** Implementation of the total_changes() SQL function. The return value is +** the same as the sqlite3_total_changes() API function. +*/ +static void total_changes( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_user_data(context); + sqlite3_result_int(context, sqlite3_total_changes(db)); +} + +/* +** A structure defining how to do GLOB-style comparisons. +*/ +struct compareInfo { + u8 matchAll; + u8 matchOne; + u8 matchSet; + u8 noCase; +}; + +/* +** For LIKE and GLOB matching on EBCDIC machines, assume that every +** character is exactly one byte in size. Also, all characters are +** able to participate in upper-case-to-lower-case mappings in EBCDIC +** whereas only characters less than 0x80 do in ASCII. +*/ +#if defined(SQLITE_EBCDIC) +# define sqlite3Utf8Read(A,B,C) (*(A++)) +# define GlogUpperToLower(A) A = sqlite3UpperToLower[A] +#else +# define GlogUpperToLower(A) if( A<0x80 ){ A = sqlite3UpperToLower[A]; } +#endif + +static const struct compareInfo globInfo = { '*', '?', '[', 0 }; +/* The correct SQL-92 behavior is for the LIKE operator to ignore +** case. Thus 'a' LIKE 'A' would be true. */ +static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 }; +/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator +** is case sensitive causing 'a' LIKE 'A' to be false */ +static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; + +/* +** Compare two UTF-8 strings for equality where the first string can +** potentially be a "glob" expression. Return true (1) if they +** are the same and false (0) if they are different. +** +** Globbing rules: +** +** '*' Matches any sequence of zero or more characters. +** +** '?' Matches exactly one character. +** +** [...] Matches one character from the enclosed list of +** characters. +** +** [^...] Matches one character not in the enclosed list. +** +** With the [...] and [^...] matching, a ']' character can be included +** in the list by making it the first character after '[' or '^'. A +** range of characters can be specified using '-'. Example: +** "[a-z]" matches any single lower-case letter. To match a '-', make +** it the last character in the list. +** +** This routine is usually quick, but can be N**2 in the worst case. +** +** Hints: to match '*' or '?', put them in "[]". Like this: +** +** abc[*]xyz Matches "abc*xyz" only +*/ +static int patternCompare( + const u8 *zPattern, /* The glob pattern */ + const u8 *zString, /* The string to compare against the glob */ + const struct compareInfo *pInfo, /* Information about how to do the compare */ + const int esc /* The escape character */ +){ + int c, c2; + int invert; + int seen; + u8 matchOne = pInfo->matchOne; + u8 matchAll = pInfo->matchAll; + u8 matchSet = pInfo->matchSet; + u8 noCase = pInfo->noCase; + int prevEscape = 0; /* True if the previous character was 'escape' */ + + while( (c = sqlite3Utf8Read(zPattern,0,&zPattern))!=0 ){ + if( !prevEscape && c==matchAll ){ + while( (c=sqlite3Utf8Read(zPattern,0,&zPattern)) == matchAll + || c == matchOne ){ + if( c==matchOne && sqlite3Utf8Read(zString, 0, &zString)==0 ){ + return 0; + } + } + if( c==0 ){ + return 1; + }else if( c==esc ){ + c = sqlite3Utf8Read(zPattern, 0, &zPattern); + if( c==0 ){ + return 0; + } + }else if( c==matchSet ){ + assert( esc==0 ); /* This is GLOB, not LIKE */ + assert( matchSet<0x80 ); /* '[' is a single-byte character */ + while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){ + SQLITE_SKIP_UTF8(zString); + } + return *zString!=0; + } + while( (c2 = sqlite3Utf8Read(zString,0,&zString))!=0 ){ + if( noCase ){ + GlogUpperToLower(c2); + GlogUpperToLower(c); + while( c2 != 0 && c2 != c ){ + c2 = sqlite3Utf8Read(zString, 0, &zString); + GlogUpperToLower(c2); + } + }else{ + while( c2 != 0 && c2 != c ){ + c2 = sqlite3Utf8Read(zString, 0, &zString); + } + } + if( c2==0 ) return 0; + if( patternCompare(zPattern,zString,pInfo,esc) ) return 1; + } + return 0; + }else if( !prevEscape && c==matchOne ){ + if( sqlite3Utf8Read(zString, 0, &zString)==0 ){ + return 0; + } + }else if( c==matchSet ){ + int prior_c = 0; + assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ + seen = 0; + invert = 0; + c = sqlite3Utf8Read(zString, 0, &zString); + if( c==0 ) return 0; + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + if( c2=='^' ){ + invert = 1; + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + } + while( c2 && c2!=']' ){ + if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){ + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; + }else{ + if( c==c2 ){ + seen = 1; + } + prior_c = c2; + } + c2 = sqlite3Utf8Read(zPattern, 0, &zPattern); + } + if( c2==0 || (seen ^ invert)==0 ){ + return 0; + } + }else if( esc==c && !prevEscape ){ + prevEscape = 1; + }else{ + c2 = sqlite3Utf8Read(zString, 0, &zString); + if( noCase ){ + GlogUpperToLower(c); + GlogUpperToLower(c2); + } + if( c!=c2 ){ + return 0; + } + prevEscape = 0; + } + } + return *zString==0; +} + +/* +** Count the number of times that the LIKE operator (or GLOB which is +** just a variation of LIKE) gets called. This is used for testing +** only. +*/ +#ifdef SQLITE_TEST +int sqlite3_like_count = 0; +#endif + + +/* +** Implementation of the like() SQL function. This function implements +** the build-in LIKE operator. The first argument to the function is the +** pattern and the second argument is the string. So, the SQL statements: +** +** A LIKE B +** +** is implemented as like(B,A). +** +** This same function (with a different compareInfo structure) computes +** the GLOB operator. +*/ +static void likeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zA, *zB; + int escape = 0; + + zB = sqlite3_value_text(argv[0]); + zA = sqlite3_value_text(argv[1]); + + /* Limit the length of the LIKE or GLOB pattern to avoid problems + ** of deep recursion and N*N behavior in patternCompare(). + */ + if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ + sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); + return; + } + assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */ + + if( argc==3 ){ + /* The escape character string must consist of a single UTF-8 character. + ** Otherwise, return an error. + */ + const unsigned char *zEsc = sqlite3_value_text(argv[2]); + if( zEsc==0 ) return; + if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ + sqlite3_result_error(context, + "ESCAPE expression must be a single character", -1); + return; + } + escape = sqlite3Utf8Read(zEsc, 0, &zEsc); + } + if( zA && zB ){ + struct compareInfo *pInfo = sqlite3_user_data(context); +#ifdef SQLITE_TEST + sqlite3_like_count++; +#endif + + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); + } +} + +/* +** Implementation of the NULLIF(x,y) function. The result is the first +** argument if the arguments are different. The result is NULL if the +** arguments are equal to each other. +*/ +static void nullifFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + CollSeq *pColl = sqlite3GetFuncCollSeq(context); + if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ + sqlite3_result_value(context, argv[0]); + } +} + +/* +** Implementation of the VERSION(*) function. The result is the version +** of the SQLite library that is running. +*/ +static void versionFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); +} + +/* Array for converting from half-bytes (nybbles) into ASCII hex +** digits. */ +static const char hexdigits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +/* +** EXPERIMENTAL - This is not an official function. The interface may +** change. This function may disappear. Do not write code that depends +** on this function. +** +** Implementation of the QUOTE() function. This function takes a single +** argument. If the argument is numeric, the return value is the same as +** the argument. If the argument is NULL, the return value is the string +** "NULL". Otherwise, the argument is enclosed in single quotes with +** single-quote escapes. +*/ +static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + if( argc<1 ) return; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: { + sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + sqlite3_result_value(context, argv[0]); + break; + } + case SQLITE_BLOB: { + char *zText = 0; + char const *zBlob = sqlite3_value_blob(argv[0]); + int nBlob = sqlite3_value_bytes(argv[0]); + assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + + if( 2*nBlob+4>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + zText = (char *)contextMalloc(context, (2*nBlob)+4); + if( zText ){ + int i; + for(i=0; i>4)&0x0F]; + zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; + } + zText[(nBlob*2)+2] = '\''; + zText[(nBlob*2)+3] = '\0'; + zText[0] = 'X'; + zText[1] = '\''; + sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); + sqlite3_free(zText); + } + break; + } + case SQLITE_TEXT: { + int i,j; + u64 n; + const unsigned char *zArg = sqlite3_value_text(argv[0]); + char *z; + + if( zArg==0 ) return; + for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } + if( i+n+3>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + z = contextMalloc(context, i+n+3); + if( z ){ + z[0] = '\''; + for(i=0, j=1; zArg[i]; i++){ + z[j++] = zArg[i]; + if( zArg[i]=='\'' ){ + z[j++] = '\''; + } + } + z[j++] = '\''; + z[j] = 0; + sqlite3_result_text(context, z, j, sqlite3_free); + } + } + } +} + +/* +** The hex() function. Interpret the argument as a blob. Return +** a hexadecimal rendering as text. +*/ +static void hexFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i, n; + const unsigned char *pBlob; + char *zHex, *z; + assert( argc==1 ); + pBlob = sqlite3_value_blob(argv[0]); + n = sqlite3_value_bytes(argv[0]); + if( n*2+1>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + z = zHex = contextMalloc(context, n*2 + 1); + if( zHex ){ + for(i=0; i>4)&0xf]; + *(z++) = hexdigits[c&0xf]; + } + *z = 0; + sqlite3_result_text(context, zHex, n*2, sqlite3_free); + } +} + +/* +** The zeroblob(N) function returns a zero-filled blob of size N bytes. +*/ +static void zeroblobFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + i64 n; + assert( argc==1 ); + n = sqlite3_value_int64(argv[0]); + if( n>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + }else{ + sqlite3_result_zeroblob(context, n); + } +} + +/* +** The replace() function. Three arguments are all strings: call +** them A, B, and C. The result is also a string which is derived +** from A by replacing every occurance of B with C. The match +** must be exact. Collating sequences are not used. +*/ +static void replaceFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zStr; /* The input string A */ + const unsigned char *zPattern; /* The pattern string B */ + const unsigned char *zRep; /* The replacement string C */ + unsigned char *zOut; /* The output */ + int nStr; /* Size of zStr */ + int nPattern; /* Size of zPattern */ + int nRep; /* Size of zRep */ + i64 nOut; /* Maximum size of zOut */ + int loopLimit; /* Last zStr[] that might match zPattern[] */ + int i, j; /* Loop counters */ + + assert( argc==3 ); + zStr = sqlite3_value_text(argv[0]); + if( zStr==0 ) return; + nStr = sqlite3_value_bytes(argv[0]); + assert( zStr==sqlite3_value_text(argv[0]) ); /* No encoding change */ + zPattern = sqlite3_value_text(argv[1]); + if( zPattern==0 || zPattern[0]==0 ) return; + nPattern = sqlite3_value_bytes(argv[1]); + assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */ + zRep = sqlite3_value_text(argv[2]); + if( zRep==0 ) return; + nRep = sqlite3_value_bytes(argv[2]); + assert( zRep==sqlite3_value_text(argv[2]) ); + nOut = nStr + 1; + assert( nOut=SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + sqlite3_free(zOut); + return; + } + zOld = zOut; + zOut = sqlite3_realloc(zOut, (int)nOut); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + sqlite3_free(zOld); + return; + } + memcpy(&zOut[j], zRep, nRep); + j += nRep; + i += nPattern-1; + } + } + assert( j+nStr-i+1==nOut ); + memcpy(&zOut[j], &zStr[i], nStr-i); + j += nStr - i; + assert( j<=nOut ); + zOut[j] = 0; + sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); +} + +/* +** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. +** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. +*/ +static void trimFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zIn; /* Input string */ + const unsigned char *zCharSet; /* Set of characters to trim */ + int nIn; /* Number of bytes in input */ + int flags; /* 1: trimleft 2: trimright 3: trim */ + int i; /* Loop counter */ + unsigned char *aLen; /* Length of each character in zCharSet */ + unsigned char **azChar; /* Individual characters in zCharSet */ + int nChar; /* Number of characters in zCharSet */ + + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + return; + } + zIn = sqlite3_value_text(argv[0]); + if( zIn==0 ) return; + nIn = sqlite3_value_bytes(argv[0]); + assert( zIn==sqlite3_value_text(argv[0]) ); + if( argc==1 ){ + static const unsigned char lenOne[] = { 1 }; + static const unsigned char *azOne[] = { (u8*)" " }; + nChar = 1; + aLen = (u8*)lenOne; + azChar = (unsigned char **)azOne; + zCharSet = 0; + }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ + return; + }else{ + const unsigned char *z; + for(z=zCharSet, nChar=0; *z; nChar++){ + SQLITE_SKIP_UTF8(z); + } + if( nChar>0 ){ + azChar = contextMalloc(context, nChar*(sizeof(char*)+1)); + if( azChar==0 ){ + return; + } + aLen = (unsigned char*)&azChar[nChar]; + for(z=zCharSet, nChar=0; *z; nChar++){ + azChar[nChar] = (unsigned char *)z; + SQLITE_SKIP_UTF8(z); + aLen[nChar] = z - azChar[nChar]; + } + } + } + if( nChar>0 ){ + flags = (int)sqlite3_user_data(context); + if( flags & 1 ){ + while( nIn>0 ){ + int len; + for(i=0; i=nChar ) break; + zIn += len; + nIn -= len; + } + } + if( flags & 2 ){ + while( nIn>0 ){ + int len; + for(i=0; i=nChar ) break; + nIn -= len; + } + } + if( zCharSet ){ + sqlite3_free(azChar); + } + } + sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); +} + +#ifdef SQLITE_SOUNDEX +/* +** Compute the soundex encoding of a word. +*/ +static void soundexFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + char zResult[8]; + const u8 *zIn; + int i, j; + static const unsigned char iCode[] = { + 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, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + }; + assert( argc==1 ); + zIn = (u8*)sqlite3_value_text(argv[0]); + if( zIn==0 ) zIn = (u8*)""; + for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} + if( zIn[i] ){ + u8 prevcode = iCode[zIn[i]&0x7f]; + zResult[0] = toupper(zIn[i]); + for(j=1; j<4 && zIn[i]; i++){ + int code = iCode[zIn[i]&0x7f]; + if( code>0 ){ + if( code!=prevcode ){ + prevcode = code; + zResult[j++] = code + '0'; + } + }else{ + prevcode = 0; + } + } + while( j<4 ){ + zResult[j++] = '0'; + } + zResult[j] = 0; + sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); + } +} +#endif + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** A function that loads a shared-library extension then returns NULL. +*/ +static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *zFile = (const char *)sqlite3_value_text(argv[0]); + const char *zProc; + sqlite3 *db = sqlite3_user_data(context); + char *zErrMsg = 0; + + if( argc==2 ){ + zProc = (const char *)sqlite3_value_text(argv[1]); + }else{ + zProc = 0; + } + if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ + sqlite3_result_error(context, zErrMsg, -1); + sqlite3_free(zErrMsg); + } +} +#endif + +#ifdef SQLITE_TEST +/* +** This function generates a string of random characters. Used for +** generating test data. +*/ +static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ + static const unsigned char zSrc[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + ".-!,:*^+=_|?/<> "; + int iMin, iMax, n, r, i; + unsigned char zBuf[1000]; + + /* It used to be possible to call randstr() with any number of arguments, + ** but now it is registered with SQLite as requiring exactly 2. + */ + assert(argc==2); + + iMin = sqlite3_value_int(argv[0]); + if( iMin<0 ) iMin = 0; + if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; + iMax = sqlite3_value_int(argv[1]); + if( iMax=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; + n = iMin; + if( iMax>iMin ){ + sqlite3Randomness(sizeof(r), &r); + r &= 0x7fffffff; + n += r%(iMax + 1 - iMin); + } + assert( ncnt++; + if( type==SQLITE_INTEGER ){ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 ){ + i64 iNewSum = p->iSum + v; + int s1 = p->iSum >> (sizeof(i64)*8-1); + int s2 = v >> (sizeof(i64)*8-1); + int s3 = iNewSum >> (sizeof(i64)*8-1); + p->overflow = (s1&s2&~s3) | (~s1&~s2&s3); + p->iSum = iNewSum; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); + p->approx = 1; + } + } +} +static void sumFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ + if( p->overflow ){ + sqlite3_result_error(context,"integer overflow",-1); + }else if( p->approx ){ + sqlite3_result_double(context, p->rSum); + }else{ + sqlite3_result_int64(context, p->iSum); + } + } +} +static void avgFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ + sqlite3_result_double(context, p->rSum/(double)p->cnt); + } +} +static void totalFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_double(context, p ? p->rSum : 0.0); +} + +/* +** The following structure keeps track of state information for the +** count() aggregate function. +*/ +typedef struct CountCtx CountCtx; +struct CountCtx { + i64 n; +}; + +/* +** Routines to implement the count() aggregate function. +*/ +static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + CountCtx *p; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ + p->n++; + } +} +static void countFinalize(sqlite3_context *context){ + CountCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_int64(context, p ? p->n : 0); +} + +/* +** Routines to implement min() and max() aggregate functions. +*/ +static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + Mem *pArg = (Mem *)argv[0]; + Mem *pBest; + + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); + if( !pBest ) return; + + if( pBest->flags ){ + int max; + int cmp; + CollSeq *pColl = sqlite3GetFuncCollSeq(context); + /* This step function is used for both the min() and max() aggregates, + ** the only difference between the two being that the sense of the + ** comparison is inverted. For the max() aggregate, the + ** sqlite3_user_data() function returns (void *)-1. For min() it + ** returns (void *)db, where db is the sqlite3* database pointer. + ** Therefore the next statement sets variable 'max' to 1 for the max() + ** aggregate, or 0 for min(). + */ + max = sqlite3_user_data(context)!=0; + cmp = sqlite3MemCompare(pBest, pArg, pColl); + if( (max && cmp<0) || (!max && cmp>0) ){ + sqlite3VdbeMemCopy(pBest, pArg); + } + }else{ + sqlite3VdbeMemCopy(pBest, pArg); + } +} +static void minMaxFinalize(sqlite3_context *context){ + sqlite3_value *pRes; + pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); + if( pRes ){ + if( pRes->flags ){ + sqlite3_result_value(context, pRes); + } + sqlite3VdbeMemRelease(pRes); + } +} + +/* +** group_concat(EXPR, ?SEPARATOR?) +*/ +static void groupConcatStep( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *zVal; + StrAccum *pAccum; + const char *zSep; + int nVal, nSep; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum)); + + if( pAccum ){ + pAccum->useMalloc = 1; + if( pAccum->nChar ){ + if( argc==2 ){ + zSep = (char*)sqlite3_value_text(argv[1]); + nSep = sqlite3_value_bytes(argv[1]); + }else{ + zSep = ","; + nSep = 1; + } + sqlite3StrAccumAppend(pAccum, zSep, nSep); + } + zVal = (char*)sqlite3_value_text(argv[0]); + nVal = sqlite3_value_bytes(argv[0]); + sqlite3StrAccumAppend(pAccum, zVal, nVal); + } +} +static void groupConcatFinalize(sqlite3_context *context){ + StrAccum *pAccum; + pAccum = sqlite3_aggregate_context(context, 0); + if( pAccum ){ + if( pAccum->tooBig ){ + sqlite3_result_error_toobig(context); + }else if( pAccum->mallocFailed ){ + sqlite3_result_error_nomem(context); + }else{ + sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, + sqlite3_free); + } + } +} + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ + static const struct { + char *zName; + signed char nArg; + u8 argType; /* ff: db 1: 0, 2: 1, 3: 2,... N: N-1. */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 needCollSeq; + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc }, + { "min", 0, 0, SQLITE_UTF8, 1, 0 }, + { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc }, + { "max", 0, 1, SQLITE_UTF8, 1, 0 }, + { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc }, + { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc }, + { "substr", 2, 0, SQLITE_UTF8, 0, substrFunc }, + { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc }, + { "abs", 1, 0, SQLITE_UTF8, 0, absFunc }, + { "round", 1, 0, SQLITE_UTF8, 0, roundFunc }, + { "round", 2, 0, SQLITE_UTF8, 0, roundFunc }, + { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, + { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, + { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, + { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, + { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, + { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc }, + { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, + { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, + { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob }, + { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, + { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, + { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, + { "last_insert_rowid", 0, 0xff, SQLITE_UTF8, 0, last_insert_rowid }, + { "changes", 0, 0xff, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 0xff, SQLITE_UTF8, 0, total_changes }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, + { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc }, + { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc }, + { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc }, + { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc }, + { "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc }, +#ifdef SQLITE_SOUNDEX + { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + { "load_extension", 1, 0xff, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 2, 0xff, SQLITE_UTF8, 0, loadExt }, +#endif +#ifdef SQLITE_TEST + { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, + { "test_destructor", 1, 0xff, SQLITE_UTF8, 0, test_destructor}, + { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, + { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, + { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, +#endif + }; + static const struct { + char *zName; + signed char nArg; + u8 argType; + u8 needCollSeq; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinalize)(sqlite3_context*); + } aAggs[] = { + { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, + { "max", 1, 1, 1, minmaxStep, minMaxFinalize }, + { "sum", 1, 0, 0, sumStep, sumFinalize }, + { "total", 1, 0, 0, sumStep, totalFinalize }, + { "avg", 1, 0, 0, sumStep, avgFinalize }, + { "count", 0, 0, 0, countStep, countFinalize }, + { "count", 1, 0, 0, countStep, countFinalize }, + { "group_concat", 1, 0, 0, groupConcatStep, groupConcatFinalize }, + { "group_concat", 2, 0, 0, groupConcatStep, groupConcatFinalize }, + }; + int i; + + for(i=0; ineedCollSeq = 1; + } + } + } +#ifndef SQLITE_OMIT_ALTERTABLE + sqlite3AlterFunctions(db); +#endif +#ifndef SQLITE_OMIT_PARSER + sqlite3AttachFunctions(db); +#endif + for(i=0; ineedCollSeq = 1; + } + } + } + sqlite3RegisterDateTimeFunctions(db); + if( !db->mallocFailed ){ + int rc = sqlite3_overload_function(db, "MATCH", 2); + assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + } + } +#ifdef SQLITE_SSE + (void)sqlite3SseFunctions(db); +#endif +#ifdef SQLITE_CASE_SENSITIVE_LIKE + sqlite3RegisterLikeFunctions(db, 1); +#else + sqlite3RegisterLikeFunctions(db, 0); +#endif +} + +/* +** Set the LIKEOPT flag on the 2-argument function with the given name. +*/ +static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){ + FuncDef *pDef; + pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0); + if( pDef ){ + pDef->flags = flagVal; + } +} + +/* +** Register the built-in LIKE and GLOB functions. The caseSensitive +** parameter determines whether or not the LIKE operator is case +** sensitive. GLOB is always case sensitive. +*/ +void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ + struct compareInfo *pInfo; + if( caseSensitive ){ + pInfo = (struct compareInfo*)&likeInfoAlt; + }else{ + pInfo = (struct compareInfo*)&likeInfoNorm; + } + sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0); + sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0); + sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, + (struct compareInfo*)&globInfo, likeFunc, 0,0); + setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); + setLikeOptFlag(db, "like", + caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); +} + +/* +** pExpr points to an expression which implements a function. If +** it is appropriate to apply the LIKE optimization to that function +** 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. +*/ +int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ + FuncDef *pDef; + if( pExpr->op!=TK_FUNCTION || !pExpr->pList ){ + return 0; + } + if( pExpr->pList->nExpr!=2 ){ + return 0; + } + pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2, + SQLITE_UTF8, 0); + if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ + return 0; + } + + /* The memcpy() statement assumes that the wildcard characters are + ** the first three statements in the compareInfo structure. The + ** asserts() that follow verify that assumption + */ + memcpy(aWc, pDef->pUserData, 3); + assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); + assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); + assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); + *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0; + return 1; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/hash.c b/client/src/thirdparty/sqlite-3.4.2/src/hash.c new file mode 100644 index 0000000..9a91e85 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/hash.c @@ -0,0 +1,419 @@ +/* +** 2001 September 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 is the implementation of generic hash-tables +** used in SQLite. +** +** $Id: hash.c,v 1.25 2008/01/22 21:30:53 drh Exp $ +*/ +#include "sqliteInt.h" +#include + +/* Turn bulk memory into a hash table object by initializing the +** fields of the Hash structure. +** +** "pNew" is a pointer to the hash table that is to be initialized. +** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER, +** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass +** determines what kind of key the hash table will use. "copyKey" is +** true if the hash table should make its own private copy of keys and +** false if it should just use the supplied pointer. CopyKey only makes +** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored +** for other key classes. +*/ +void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){ + assert( pNew!=0 ); + assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY ); + pNew->keyClass = keyClass; +#if 0 + if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0; +#endif + pNew->copyKey = copyKey; + pNew->first = 0; + pNew->count = 0; + pNew->htsize = 0; + pNew->ht = 0; +} + +/* Remove all entries from a hash table. Reclaim all memory. +** Call this routine to delete a hash table or to reset a hash table +** to the empty state. +*/ +void sqlite3HashClear(Hash *pH){ + HashElem *elem; /* For looping over all elements of the table */ + + assert( pH!=0 ); + elem = pH->first; + pH->first = 0; + if( pH->ht ) sqlite3_free(pH->ht); + pH->ht = 0; + pH->htsize = 0; + while( elem ){ + HashElem *next_elem = elem->next; + if( pH->copyKey && elem->pKey ){ + sqlite3_free(elem->pKey); + } + sqlite3_free(elem); + elem = next_elem; + } + pH->count = 0; +} + +#if 0 /* NOT USED */ +/* +** Hash and comparison functions when the mode is SQLITE_HASH_INT +*/ +static int intHash(const void *pKey, int nKey){ + return nKey ^ (nKey<<8) ^ (nKey>>8); +} +static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + return n2 - n1; +} +#endif + +#if 0 /* NOT USED */ +/* +** Hash and comparison functions when the mode is SQLITE_HASH_POINTER +*/ +static int ptrHash(const void *pKey, int nKey){ + uptr x = Addr(pKey); + return x ^ (x<<8) ^ (x>>8); +} +static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( pKey1==pKey2 ) return 0; + if( pKey1 0 ){ + h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++]; + nKey--; + } + return h & 0x7fffffff; +} +static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1); +} + +/* +** Hash and comparison functions when the mode is SQLITE_HASH_BINARY +*/ +static int binHash(const void *pKey, int nKey){ + int h = 0; + const char *z = (const char *)pKey; + while( nKey-- > 0 ){ + h = (h<<3) ^ h ^ *(z++); + } + return h & 0x7fffffff; +} +static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ + if( n1!=n2 ) return 1; + return memcmp(pKey1,pKey2,n1); +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** The C syntax in this function definition may be unfamilar to some +** programmers, so we provide the following additional explanation: +** +** The name of the function is "hashFunction". The function takes a +** single parameter "keyClass". The return value of hashFunction() +** is a pointer to another function. Specifically, the return value +** of hashFunction() is a pointer to a function that takes two parameters +** with types "const void*" and "int" and returns an "int". +*/ +static int (*hashFunction(int keyClass))(const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ + switch( keyClass ){ + case SQLITE_HASH_INT: return &intHash; + case SQLITE_HASH_POINTER: return &ptrHash; + case SQLITE_HASH_STRING: return &strHash; + case SQLITE_HASH_BINARY: return &binHash;; + default: break; + } + return 0; +#else + if( keyClass==SQLITE_HASH_STRING ){ + return &strHash; + }else{ + assert( keyClass==SQLITE_HASH_BINARY ); + return &binHash; + } +#endif +} + +/* +** Return a pointer to the appropriate hash function given the key class. +** +** For help in interpreted the obscure C code in the function definition, +** see the header comment on the previous function. +*/ +static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ + switch( keyClass ){ + case SQLITE_HASH_INT: return &intCompare; + case SQLITE_HASH_POINTER: return &ptrCompare; + case SQLITE_HASH_STRING: return &strCompare; + case SQLITE_HASH_BINARY: return &binCompare; + default: break; + } + return 0; +#else + if( keyClass==SQLITE_HASH_STRING ){ + return &strCompare; + }else{ + assert( keyClass==SQLITE_HASH_BINARY ); + return &binCompare; + } +#endif +} + +/* Link an element into the hash table +*/ +static void insertElement( + Hash *pH, /* The complete hash table */ + struct _ht *pEntry, /* The entry into which pNew is inserted */ + HashElem *pNew /* The element to be inserted */ +){ + HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; +} + + +/* Resize the hash table so that it cantains "new_size" buckets. +** "new_size" must be a power of 2. The hash table might fail +** to resize if sqlite3_malloc() fails. +*/ +static void rehash(Hash *pH, int new_size){ + struct _ht *new_ht; /* The new hash table */ + HashElem *elem, *next_elem; /* For looping over existing elements */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( (new_size & (new_size-1))==0 ); + + /* There is a call to sqlite3_malloc() inside rehash(). If there is + ** already an allocation at pH->ht, then if this malloc() fails it + ** is benign (since failing to resize a hash table is a performance + ** hit only, not a fatal error). + */ + sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pH->htsize>0); + new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) ); + sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + + if( new_ht==0 ) return; + if( pH->ht ) sqlite3_free(pH->ht); + pH->ht = new_ht; + pH->htsize = new_size; + xHash = hashFunction(pH->keyClass); + for(elem=pH->first, pH->first=0; elem; elem = next_elem){ + int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + next_elem = elem->next; + insertElement(pH, &new_ht[h], elem); + } +} + +/* This function (for internal use only) locates an element in an +** hash table that matches the given key. The hash for this key has +** already been computed and is passed as the 4th parameter. +*/ +static HashElem *findElementGivenHash( + const Hash *pH, /* The pH to be searched */ + const void *pKey, /* The key we are searching for */ + int nKey, + int h /* The hash for this key. */ +){ + HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + int (*xCompare)(const void*,int,const void*,int); /* comparison function */ + + if( pH->ht ){ + struct _ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + xCompare = compareFunction(pH->keyClass); + while( count-- && elem ){ + if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + } + return 0; +} + +/* Remove a single entry from the hash table given a pointer to that +** element and a hash on the element's key. +*/ +static void removeElementGivenHash( + Hash *pH, /* The pH containing "elem" */ + HashElem* elem, /* The element to be removed from the pH */ + int h /* Hash value for the element */ +){ + struct _ht *pEntry; + if( elem->prev ){ + elem->prev->next = elem->next; + }else{ + pH->first = elem->next; + } + if( elem->next ){ + elem->next->prev = elem->prev; + } + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; + } + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; + } + if( pH->copyKey ){ + sqlite3_free(elem->pKey); + } + sqlite3_free( elem ); + pH->count--; + if( pH->count<=0 ){ + assert( pH->first==0 ); + assert( pH->count==0 ); + sqlite3HashClear(pH); + } +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return a pointer to the corresponding +** HashElem structure for this element if it is found, or NULL +** otherwise. +*/ +HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){ + int h; /* A hash on key */ + HashElem *elem; /* The element that matches key */ + int (*xHash)(const void*,int); /* The hash function */ + + if( pH==0 || pH->ht==0 ) return 0; + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + h = (*xHash)(pKey,nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1)); + return elem; +} + +/* Attempt to locate an element of the hash table pH with a key +** that matches pKey,nKey. Return the data for this element if it is +** found, or NULL if there is no match. +*/ +void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){ + HashElem *elem; /* The element that matches key */ + elem = sqlite3HashFindElem(pH, pKey, nKey); + return elem ? elem->data : 0; +} + +/* Insert an element into the hash table pH. The key is pKey,nKey +** and the data is "data". +** +** If no element exists with a matching key, then a new +** element is created. A copy of the key is made if the copyKey +** flag is set. NULL is returned. +** +** If another element already exists with the same key, then the +** new data replaces the old data and the old data is returned. +** The key is not copied in this instance. If a malloc fails, then +** the new data is returned and the hash table is unchanged. +** +** If the "data" parameter to this function is NULL, then the +** element corresponding to "key" is removed from the hash table. +*/ +void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ + int hraw; /* Raw hash value of the key */ + int h; /* the hash of the key modulo hash table size */ + HashElem *elem; /* Used to loop thru the element list */ + HashElem *new_elem; /* New element added to the pH */ + int (*xHash)(const void*,int); /* The hash function */ + + assert( pH!=0 ); + xHash = hashFunction(pH->keyClass); + assert( xHash!=0 ); + hraw = (*xHash)(pKey, nKey); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + elem = findElementGivenHash(pH,pKey,nKey,h); + if( elem ){ + void *old_data = elem->data; + if( data==0 ){ + removeElementGivenHash(pH,elem,h); + }else{ + elem->data = data; + if( !pH->copyKey ){ + elem->pKey = (void *)pKey; + } + assert(nKey==elem->nKey); + } + return old_data; + } + if( data==0 ) return 0; + new_elem = (HashElem*)sqlite3_malloc( sizeof(HashElem) ); + if( new_elem==0 ) return data; + if( pH->copyKey && pKey!=0 ){ + new_elem->pKey = sqlite3_malloc( nKey ); + if( new_elem->pKey==0 ){ + sqlite3_free(new_elem); + return data; + } + memcpy((void*)new_elem->pKey, pKey, nKey); + }else{ + new_elem->pKey = (void*)pKey; + } + new_elem->nKey = nKey; + pH->count++; + if( pH->htsize==0 ){ + rehash(pH,8); + if( pH->htsize==0 ){ + pH->count = 0; + if( pH->copyKey ){ + sqlite3_free(new_elem->pKey); + } + sqlite3_free(new_elem); + return data; + } + } + if( pH->count > pH->htsize ){ + rehash(pH,pH->htsize*2); + } + assert( pH->htsize>0 ); + assert( (pH->htsize & (pH->htsize-1))==0 ); + h = hraw & (pH->htsize-1); + insertElement(pH, &pH->ht[h], new_elem); + new_elem->data = data; + return 0; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/hash.h b/client/src/thirdparty/sqlite-3.4.2/src/hash.h new file mode 100644 index 0000000..e3274e9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/hash.h @@ -0,0 +1,110 @@ +/* +** 2001 September 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 is the header file for the generic hash-table implemenation +** used in SQLite. +** +** $Id: hash.h,v 1.11 2007/09/04 14:31:47 danielk1977 Exp $ +*/ +#ifndef _SQLITE_HASH_H_ +#define _SQLITE_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, many of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +*/ +struct Hash { + char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */ + char copyKey; /* True if copy of key made on insert */ + int count; /* Number of entries in this table */ + int htsize; /* Number of buckets in the hash table */ + HashElem *first; /* The first element of the array */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + void *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** There are 4 different modes of operation for a hash table: +** +** SQLITE_HASH_INT nKey is used as the key and pKey is ignored. +** +** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored. +** +** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long +** (including the null-terminator, if any). Case +** is ignored in comparisons. +** +** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long. +** memcmp() is used to compare keys. +** +** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY +** if the copyKey parameter to HashInit is 1. +*/ +/* #define SQLITE_HASH_INT 1 // NOT USED */ +/* #define SQLITE_HASH_POINTER 2 // NOT USED */ +#define SQLITE_HASH_STRING 3 +#define SQLITE_HASH_BINARY 4 + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +void sqlite3HashInit(Hash*, int keytype, int copyKey); +void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData); +void *sqlite3HashFind(const Hash*, const void *pKey, int nKey); +HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey); +void sqlite3HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ +** SomeStructure *pData = sqliteHashData(p); +** // do something with pData +** } +*/ +#define sqliteHashFirst(H) ((H)->first) +#define sqliteHashNext(E) ((E)->next) +#define sqliteHashData(E) ((E)->data) +#define sqliteHashKey(E) ((E)->pKey) +#define sqliteHashKeysize(E) ((E)->nKey) + +/* +** Number of entries in a hash table +*/ +#define sqliteHashCount(H) ((H)->count) + +#endif /* _SQLITE_HASH_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/insert.c b/client/src/thirdparty/sqlite-3.4.2/src/insert.c new file mode 100644 index 0000000..07b069c --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/insert.c @@ -0,0 +1,1663 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains C code routines that are called by the parser +** to handle INSERT statements in SQLite. +** +** $Id: insert.c,v 1.228 2008/01/25 15:04:50 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** Set P4 of the most recently inserted opcode to a column affinity +** string for index pIdx. A column affinity string has one character +** for each column in the table, according to the affinity of the column: +** +** Character Column affinity +** ------------------------------ +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL +** +** An extra 'b' is appended to the end of the string to cover the +** rowid that appears as the last column in every index. +*/ +void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ + if( !pIdx->zColAff ){ + /* The first time a column affinity string for a particular index is + ** required, it is allocated and populated here. It is then stored as + ** a member of the Index structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqliteDeleteIndex() when the Index structure itself is cleaned + ** up. + */ + int n; + Table *pTab = pIdx->pTable; + sqlite3 *db = sqlite3VdbeDb(v); + pIdx->zColAff = (char *)sqlite3DbMallocZero(db, pIdx->nColumn+2); + if( !pIdx->zColAff ){ + return; + } + for(n=0; nnColumn; n++){ + pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; + } + pIdx->zColAff[n++] = SQLITE_AFF_NONE; + pIdx->zColAff[n] = 0; + } + + sqlite3VdbeChangeP4(v, -1, pIdx->zColAff, 0); +} + +/* +** Set P4 of the most recently inserted opcode to a column affinity +** string for table pTab. A column affinity string has one character +** for each column indexed by the index, according to the affinity of the +** column: +** +** Character Column affinity +** ------------------------------ +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL +*/ +void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ + /* The first time a column affinity string for a particular table + ** is required, it is allocated and populated here. It is then + ** stored as a member of the Table structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqlite3DeleteTable() when the Table structure itself is cleaned up. + */ + if( !pTab->zColAff ){ + char *zColAff; + int i; + sqlite3 *db = sqlite3VdbeDb(v); + + zColAff = (char *)sqlite3DbMallocZero(db, pTab->nCol+1); + if( !zColAff ){ + return; + } + + for(i=0; inCol; i++){ + zColAff[i] = pTab->aCol[i].affinity; + } + zColAff[pTab->nCol] = '\0'; + + pTab->zColAff = zColAff; + } + + sqlite3VdbeChangeP4(v, -1, pTab->zColAff, 0); +} + +/* +** Return non-zero if the table pTab in database iDb or any of its indices +** have been opened at any point in the VDBE program beginning at location +** iStartAddr throught the end of the program. This is used to see if +** a statement of the form "INSERT INTO SELECT ..." can +** run without using temporary table for the results of the SELECT. +*/ +static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){ + int i; + int iEnd = sqlite3VdbeCurrentAddr(v); + for(i=iStartAddr; iopcode==OP_OpenRead && pOp->p3==iDb ){ + Index *pIndex; + int tnum = pOp->p2; + if( tnum==pTab->tnum ){ + return 1; + } + for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ + if( tnum==pIndex->tnum ){ + return 1; + } + } + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pTab->pVtab ){ + assert( pOp->p4.pVtab!=0 ); + assert( pOp->p4type==P4_VTAB ); + return 1; + } +#endif + } + return 0; +} + +#ifndef SQLITE_OMIT_AUTOINCREMENT +/* +** Write out code to initialize the autoincrement logic. This code +** looks up the current autoincrement value in the sqlite_sequence +** table and stores that value in a register. Code generated by +** autoIncStep() will keep that register holding the largest +** rowid value. Code generated by autoIncEnd() will write the new +** largest value of the counter back into the sqlite_sequence table. +** +** This routine returns the index of the mem[] cell that contains +** the maximum rowid counter. +** +** Three consecutive registers are allocated by this routine. The +** first two hold the name of the target table and the maximum rowid +** inserted into the target table, respectively. +** The third holds the rowid in sqlite_sequence where we will +** write back the revised maximum rowid. This routine returns the +** index of the second of these three registers. +*/ +static int autoIncBegin( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab /* The table we are writing to */ +){ + int memId = 0; /* Register holding maximum rowid */ + if( pTab->autoInc ){ + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int iCur = pParse->nTab; + int addr; /* Address of the top of the loop */ + assert( v ); + pParse->nMem++; /* Holds name of table */ + memId = ++pParse->nMem; + pParse->nMem++; + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+8); + sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, memId); + sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); + sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+8); + sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+2); + sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); + } + return memId; +} + +/* +** Update the maximum rowid for an autoincrement calculation. +** +** This routine should be called when the top of the stack holds a +** new rowid that is about to be inserted. If that new rowid is +** larger than the maximum rowid in the memId memory cell, then the +** memory cell is updated. The stack is unchanged. +*/ +static void autoIncStep(Parse *pParse, int memId, int regRowid){ + if( memId>0 ){ + sqlite3VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid); + } +} + +/* +** After doing one or more inserts, the maximum rowid is stored +** in reg[memId]. Generate code to write this value back into the +** the sqlite_sequence table. +*/ +static void autoIncEnd( + Parse *pParse, /* The parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab, /* Table we are inserting into */ + int memId /* Memory cell holding the maximum rowid */ +){ + if( pTab->autoInc ){ + int iCur = pParse->nTab; + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int j1; + + assert( v ); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); + sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, memId-1); + sqlite3VdbeAddOp3(v, OP_Insert, iCur, memId-1, memId+1); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3VdbeAddOp1(v, OP_Close, iCur); + } +} +#else +/* +** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines +** above are all no-ops +*/ +# define autoIncBegin(A,B,C) (0) +# define autoIncStep(A,B,C) +# define autoIncEnd(A,B,C,D) +#endif /* SQLITE_OMIT_AUTOINCREMENT */ + + +/* Forward declaration */ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +); + +/* +** This routine is call to handle SQL of the following forms: +** +** insert into TABLE (IDLIST) values(EXPRLIST) +** insert into TABLE (IDLIST) select +** +** 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. +** +** 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. +** +** The code generated follows one of four templates. For a simple +** select with data coming from a VALUES clause, the code executes +** once straight down through. The template looks like this: +** +** open write cursor to
and its indices +** puts VALUES clause expressions onto the stack +** write the resulting record into
+** cleanup +** +** The three remaining templates assume the statement is of the form +** +** INSERT INTO
SELECT ... +** +** If the SELECT clause is of the restricted form "SELECT * FROM " - +** in other words if the SELECT pulls all columns from a single table +** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and +** if and are distinct tables but have identical +** schemas, including all the same indices, then a special optimization +** is invoked that copies raw records from over to . +** See the xferOptimization() function for the implementation of this +** template. This is the second template. +** +** open a write cursor to
+** open read cursor on +** transfer all records in over to
+** close cursors +** foreach index on
+** open a write cursor on the
index +** open a read cursor on the corresponding index +** transfer all records from the read to the write cursors +** close cursors +** end foreach +** +** The third template is for when the second template does not apply +** and the SELECT clause does not read from
at any time. +** The generated code follows this template: +** +** goto B +** A: setup for the SELECT +** loop over the rows in the SELECT +** gosub C +** end loop +** cleanup after the SELECT +** goto D +** B: open write cursor to
and its indices +** goto A +** C: insert the select result into
+** return +** D: cleanup +** +** The fourth template is used if the insert statement takes its +** values from a SELECT but the data is being inserted into a table +** that is also read as part of the SELECT. In the third form, +** we have to use a intermediate table to store the results of +** the select. The template is like this: +** +** goto B +** A: setup for the SELECT +** loop over the tables in the SELECT +** gosub C +** end loop +** cleanup after the SELECT +** goto D +** C: insert the select result into the intermediate table +** return +** B: open a cursor to an intermediate table +** goto A +** D: open write cursor to
and its indices +** loop over the intermediate table +** transfer values form intermediate table into
+** end the loop +** cleanup +*/ +void sqlite3Insert( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* Name of table into which we are inserting */ + ExprList *pList, /* List of values to be inserted */ + Select *pSelect, /* A SELECT statement to use as the data source */ + IdList *pColumn, /* Column names corresponding to IDLIST. */ + int onError /* How to handle constraint errors */ +){ + sqlite3 *db; /* The main database structure */ + Table *pTab; /* The table to insert into. aka TABLE */ + char *zTab; /* Name of the table into which we are inserting */ + const char *zDb; /* Name of the database holding this table */ + int i, j, idx; /* Loop counters */ + Vdbe *v; /* Generate code into this virtual machine */ + Index *pIdx; /* For looping over indices of the table */ + int nColumn; /* Number of columns in the data */ + int nHidden = 0; /* Number of hidden columns if TABLE is virtual */ + int baseCur = 0; /* VDBE Cursor number for pTab */ + int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ + int endOfLoop; /* Label for the end of the insertion loop */ + int useTempTable = 0; /* Store SELECT results in intermediate table */ + int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ + int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ + int iSelectLoop = 0; /* Address of code that implements the SELECT */ + int iCleanup = 0; /* Address of the cleanup code */ + int iInsertBlock = 0; /* Address of the subroutine used to insert data */ + int newIdx = -1; /* Cursor for the NEW pseudo-table */ + int iDb; /* Index of database holding TABLE */ + Db *pDb; /* The database containing table being inserted into */ + int appendFlag = 0; /* True if the insert is likely to be an append */ + + /* Register allocations */ + int regFromSelect; /* Base register for data coming from SELECT */ + int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */ + int regRowCount = 0; /* Memory cell used for the row counter */ + int regIns; /* Block of regs holding rowid+data being inserted */ + int regRowid; /* registers holding insert rowid */ + int regData; /* register holding first column to insert */ + int regRecord; /* Holds the assemblied row record */ + int *aRegIdx = 0; /* One register allocated to each index */ + + +#ifndef SQLITE_OMIT_TRIGGER + int isView; /* True if attempting to insert into a view */ + int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ +#endif + + db = pParse->db; + if( pParse->nErr || db->mallocFailed ){ + goto insert_cleanup; + } + + /* Locate the table into which we will be inserting new information. + */ + assert( pTabList->nSrc==1 ); + zTab = pTabList->a[0].zName; + if( zTab==0 ) goto insert_cleanup; + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ){ + goto insert_cleanup; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + pDb = &db->aDb[iDb]; + zDb = pDb->zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ + goto insert_cleanup; + } + + /* Figure out if we have any triggers and if the table being + ** inserted into is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0); + isView = pTab->pSelect!=0; +#else +# define triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + + /* Ensure that: + * (a) the table is not read-only, + * (b) that if it is a view then ON INSERT triggers exist + */ + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ + goto insert_cleanup; + } + assert( pTab!=0 ); + + /* If pTab is really a view, make sure it has been initialized. + ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual + ** module table). + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto insert_cleanup; + } + + /* Allocate a VDBE + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto insert_cleanup; + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); + sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb); + + /* if there are row triggers, allocate a temp table for new.* references. */ + if( triggers_exist ){ + newIdx = pParse->nTab++; + } + +#ifndef SQLITE_OMIT_XFER_OPT + /* If the statement is of the form + ** + ** INSERT INTO SELECT * FROM ; + ** + ** Then special optimizations can be applied that make the transfer + ** very fast and which reduce fragmentation of indices. + */ + if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ + assert( !triggers_exist ); + assert( pList==0 ); + goto insert_cleanup; + } +#endif /* SQLITE_OMIT_XFER_OPT */ + + /* If this is an AUTOINCREMENT table, look up the sequence number in the + ** sqlite_sequence table and store it in memory cell regAutoinc. + */ + regAutoinc = autoIncBegin(pParse, iDb, pTab); + + /* Figure out how many columns of data are supplied. If the data + ** is coming from a SELECT statement, then this step also generates + ** all the code to implement the SELECT statement and invoke a subroutine + ** to process each row of the result. (Template 2.) If the SELECT + ** statement uses the the table that is being inserted into, then the + ** subroutine is also coded here. That subroutine stores the SELECT + ** results in a temporary table. (Template 3.) + */ + if( pSelect ){ + /* Data is coming from a SELECT. Generate code to implement that SELECT + */ + SelectDest dest; + int rc, iInitCode; + + iInitCode = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + iSelectLoop = sqlite3VdbeCurrentAddr(v); + iInsertBlock = sqlite3VdbeMakeLabel(v); + sqlite3SelectDestInit(&dest, SRT_Subroutine, iInsertBlock); + + /* Resolve the expressions in the SELECT statement and execute it. */ + rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); + if( rc || pParse->nErr || db->mallocFailed ){ + goto insert_cleanup; + } + + regFromSelect = dest.iMem; + iCleanup = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup); + assert( pSelect->pEList ); + nColumn = pSelect->pEList->nExpr; + + /* Set useTempTable to TRUE if the result of the SELECT statement + ** should be written into a temporary table. Set to FALSE if each + ** row of the SELECT can be written directly into the result table. + ** + ** A temp table must be used if the table being updated is also one + ** of the tables being read by the SELECT statement. Also use a + ** temp table in the case of row triggers. + */ + if( triggers_exist || readsTable(v, iSelectLoop, iDb, pTab) ){ + useTempTable = 1; + } + + if( useTempTable ){ + /* Generate the subroutine that SELECT calls to process each row of + ** the result. Store the result in a temporary table + */ + int regRec, regRowid; + + srcTab = pParse->nTab++; + regRec = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + sqlite3VdbeResolveLabel(v, iInsertBlock); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); + sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid); + sqlite3VdbeAddOp2(v, OP_Return, 0, 0); + sqlite3ReleaseTempReg(pParse, regRec); + sqlite3ReleaseTempReg(pParse, regRowid); + + /* The following code runs first because the GOTO at the very top + ** of the program jumps to it. Create the temporary table, then jump + ** back up and execute the SELECT code above. + */ + sqlite3VdbeJumpHere(v, iInitCode); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, 0); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, srcTab, nColumn); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); + sqlite3VdbeResolveLabel(v, iCleanup); + }else{ + sqlite3VdbeJumpHere(v, iInitCode); + } + }else{ + /* This is the case if the data for the INSERT is coming from a VALUES + ** clause + */ + NameContext sNC; + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + srcTab = -1; + assert( useTempTable==0 ); + nColumn = pList ? pList->nExpr : 0; + for(i=0; ia[i].pExpr) ){ + goto insert_cleanup; + } + } + } + + /* Make sure the number of columns in the source data matches the number + ** of columns to be inserted into the table. + */ + if( IsVirtual(pTab) ){ + for(i=0; inCol; i++){ + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); + } + } + if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ + sqlite3ErrorMsg(pParse, + "table %S has %d columns but %d values were supplied", + pTabList, 0, pTab->nCol, nColumn); + goto insert_cleanup; + } + if( pColumn!=0 && nColumn!=pColumn->nId ){ + sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); + goto insert_cleanup; + } + + /* If the INSERT statement included an IDLIST term, then make sure + ** all elements of the IDLIST really are columns of the table and + ** remember the column indices. + ** + ** If the table has an INTEGER PRIMARY KEY column and that column + ** is named in the IDLIST, then record in the keyColumn variable + ** the index into IDLIST of the primary key column. keyColumn is + ** the index of the primary key as it appears in IDLIST, not as + ** is appears in the original table. (The index of the primary + ** key in the original table is pTab->iPKey.) + */ + if( pColumn ){ + for(i=0; inId; i++){ + pColumn->a[i].idx = -1; + } + for(i=0; inId; i++){ + for(j=0; jnCol; j++){ + if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ + pColumn->a[i].idx = j; + if( j==pTab->iPKey ){ + keyColumn = i; + } + break; + } + } + if( j>=pTab->nCol ){ + if( sqlite3IsRowid(pColumn->a[i].zName) ){ + keyColumn = i; + }else{ + sqlite3ErrorMsg(pParse, "table %S has no column named %s", + pTabList, 0, pColumn->a[i].zName); + pParse->nErr++; + goto insert_cleanup; + } + } + } + } + + /* If there is no IDLIST term but the table has an integer primary + ** key, the set the keyColumn variable to the primary key column index + ** in the original table definition. + */ + if( pColumn==0 && nColumn>0 ){ + keyColumn = pTab->iPKey; + } + + /* Open the temp table for FOR EACH ROW triggers + */ + if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); + } + + /* Initialize the count of rows to be inserted + */ + if( db->flags & SQLITE_CountRows ){ + regRowCount = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount); + } + + /* If this is not a view, open the table and and all indices */ + if( !isView ){ + int nIdx; + int i; + + baseCur = pParse->nTab; + nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite); + aRegIdx = sqlite3DbMallocZero(db, sizeof(int)*(nIdx+1)); + if( aRegIdx==0 ){ + goto insert_cleanup; + } + for(i=0; inMem; + } + } + + /* If the data source is a temporary table, then we have to create + ** a loop because there might be multiple rows of data. If the data + ** source is a subroutine call from the SELECT statement, then we need + ** to launch the SELECT statement processing. + */ + if( useTempTable ){ + iBreak = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp2(v, OP_Rewind, srcTab, iBreak); + iCont = sqlite3VdbeCurrentAddr(v); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); + sqlite3VdbeResolveLabel(v, iInsertBlock); + } + + /* Allocate registers for holding the rowid of the new row, + ** the content of the new row, and the assemblied row record. + */ + regRecord = ++pParse->nMem; + regRowid = regIns = pParse->nMem+1; + pParse->nMem += pTab->nCol + 1; + if( IsVirtual(pTab) ){ + regRowid++; + pParse->nMem++; + } + regData = regRowid+1; + + /* Run the BEFORE and INSTEAD OF triggers, if there are any + */ + endOfLoop = sqlite3VdbeMakeLabel(v); + if( triggers_exist & TRIGGER_BEFORE ){ + int regRowid; + int regCols; + int regRec; + + /* build the NEW.* reference row. Note that if there is an INTEGER + ** PRIMARY KEY into which a NULL is being inserted, that NULL will be + ** translated into a unique ID for the row. But on a BEFORE trigger, + ** we do not know what the unique ID will be (because the insert has + ** not happened yet) so we substitute a rowid of -1 + */ + regRowid = sqlite3GetTempReg(pParse); + if( keyColumn<0 ){ + sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); + }else{ + int j1; + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); + sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); + } + + /* Cannot have triggers on a virtual table. If it were possible, + ** this block would have to account for hidden column. + */ + assert(!IsVirtual(pTab)); + + /* Create the new column data + */ + regCols = sqlite3GetTempRange(pParse, pTab->nCol); + for(i=0; inCol; i++){ + if( pColumn==0 ){ + j = i; + }else{ + for(j=0; jnId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( pColumn && j>=pColumn->nId ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i); + }else{ + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i); + } + } + regRec = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRec); + + /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, + ** do not attempt any conversions before assembling the record. + ** If this is a real table, attempt conversions as required by the + ** table column affinities. + */ + if( !isView ){ + sqlite3TableAffinityStr(v, pTab); + } + sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); + sqlite3ReleaseTempReg(pParse, regRec); + sqlite3ReleaseTempReg(pParse, regRowid); + sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); + + /* Fire BEFORE or INSTEAD OF triggers */ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, + newIdx, -1, onError, endOfLoop, 0, 0) ){ + goto insert_cleanup; + } + } + + /* Push the record number for the new entry onto the stack. The + ** record number is a randomly generate integer created by NewRowid + ** except when the table has an INTEGER PRIMARY KEY column, in which + ** case the record number is the same as that column. + */ + if( !isView ){ + if( IsVirtual(pTab) ){ + /* The row that the VUpdate opcode will delete: none */ + sqlite3VdbeAddOp2(v, OP_Null, 0, regIns); + } + if( keyColumn>=0 ){ + if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid); + }else{ + VdbeOp *pOp; + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid); + pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); + if( pOp && pOp->opcode==OP_Null ){ + appendFlag = 1; + pOp->opcode = OP_NewRowid; + pOp->p1 = baseCur; + pOp->p2 = regRowid; + pOp->p3 = regAutoinc; + } + } + /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid + ** to generate a unique primary key value. + */ + if( !appendFlag ){ + int j1; + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid); + sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); + } + }else if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid); + }else{ + sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc); + appendFlag = 1; + } + autoIncStep(pParse, regAutoinc, regRowid); + + /* Push onto the stack, data for all columns of the new entry, beginning + ** with the first column. + */ + nHidden = 0; + for(i=0; inCol; i++){ + int iRegStore = regRowid+1+i; + if( i==pTab->iPKey ){ + /* The value of the INTEGER PRIMARY KEY column is always a NULL. + ** Whenever this column is read, the record number will be substituted + ** in its place. So will fill this column with a NULL to avoid + ** taking up data space with information that will never be used. */ + sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore); + continue; + } + if( pColumn==0 ){ + if( IsHiddenColumn(&pTab->aCol[i]) ){ + assert( IsVirtual(pTab) ); + j = -1; + nHidden++; + }else{ + j = i - nHidden; + } + }else{ + for(j=0; jnId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore); + }else if( useTempTable ){ + sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore); + }else{ + sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore); + } + } + + /* Generate code to check constraints and generate index keys and + ** do the insertion. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + pParse->pVirtualLock = pTab; + sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, + (const char*)pTab->pVtab, P4_VTAB); + }else +#endif + { + sqlite3GenerateConstraintChecks( + pParse, + pTab, + baseCur, + regIns, + aRegIdx, + keyColumn>=0, + 0, + onError, + endOfLoop + ); + sqlite3CompleteInsertion( + pParse, + pTab, + baseCur, + regIns, + aRegIdx, + 0, + 0, + (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, + appendFlag + ); + } + } + + /* Update the count of rows that are inserted + */ + if( (db->flags & SQLITE_CountRows)!=0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1); + } + + if( triggers_exist ){ + /* Code AFTER triggers */ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab, + newIdx, -1, onError, endOfLoop, 0, 0) ){ + goto insert_cleanup; + } + } + + /* The bottom of the loop, if the data source is a SELECT statement + */ + sqlite3VdbeResolveLabel(v, endOfLoop); + if( useTempTable ){ + sqlite3VdbeAddOp2(v, OP_Next, srcTab, iCont); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, srcTab, 0); + }else if( pSelect ){ + sqlite3VdbeAddOp2(v, OP_Return, 0, 0); + sqlite3VdbeResolveLabel(v, iCleanup); + } + + if( !IsVirtual(pTab) && !isView ){ + /* Close all tables opened */ + sqlite3VdbeAddOp2(v, OP_Close, baseCur, 0); + for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ + sqlite3VdbeAddOp2(v, OP_Close, idx+baseCur, 0); + } + } + + /* Update the sqlite_sequence table by storing the content of the + ** counter value in memory regAutoinc back into the sqlite_sequence + ** table. + */ + autoIncEnd(pParse, iDb, pTab, regAutoinc); + + /* + ** Return the number of rows inserted. If this routine is + ** generating code because of a call to sqlite3NestedParse(), do not + ** invoke the callback function. + */ + if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC); + } + +insert_cleanup: + sqlite3SrcListDelete(pTabList); + sqlite3ExprListDelete(pList); + sqlite3SelectDelete(pSelect); + sqlite3IdListDelete(pColumn); + sqlite3_free(aRegIdx); +} + +/* +** Generate code to do constraint checks prior to an INSERT or an UPDATE. +** +** The input is a range of consecutive registers as follows: +** +** 1. The rowid of the row to be updated before the update. This +** value is omitted unless we are doing an UPDATE that involves a +** change to the record number or writing to a virtual table. +** +** 2. The rowid of the row after the update. +** +** 3. The data in the first column of the entry after the update. +** +** i. Data from middle columns... +** +** N. The data in the last column of the entry after the update. +** +** The regRowid parameter is the index of the register containing (2). +** +** The old rowid shown as entry (1) above is omitted unless both isUpdate +** and rowidChng are 1. isUpdate is true for UPDATEs and false for +** INSERTs. RowidChng means that the new rowid is explicitly specified by +** the update or insert statement. If rowidChng is false, it means that +** the rowid is computed automatically in an insert or that the rowid value +** is not modified by the update. +** +** The code generated by this routine store new index entries into +** registers identified by aRegIdx[]. No index entry is created for +** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is +** the same as the order of indices on the linked list of indices +** attached to the table. +** +** This routine also generates code to check constraints. NOT NULL, +** CHECK, and UNIQUE constraints are all checked. If a constraint fails, +** then the appropriate action is performed. There are five possible +** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE. +** +** Constraint type Action What Happens +** --------------- ---------- ---------------------------------------- +** any ROLLBACK The current transaction is rolled back and +** sqlite3_exec() returns immediately with a +** return code of SQLITE_CONSTRAINT. +** +** any ABORT Back out changes from the current command +** only (do not do a complete rollback) then +** cause sqlite3_exec() to return immediately +** with SQLITE_CONSTRAINT. +** +** any FAIL Sqlite_exec() returns immediately with a +** return code of SQLITE_CONSTRAINT. The +** transaction is not rolled back and any +** prior changes are retained. +** +** any IGNORE The record number and data is popped from +** the stack and there is an immediate jump +** to label ignoreDest. +** +** NOT NULL REPLACE The NULL value is replace by the default +** value for that column. If the default value +** is NULL, the action is the same as ABORT. +** +** UNIQUE REPLACE The other row that conflicts with the row +** being inserted is removed. +** +** CHECK REPLACE Illegal. The results in an exception. +** +** Which action to take is determined by the overrideError parameter. +** Or if overrideError==OE_Default, then the pParse->onError parameter +** is used. Or if pParse->onError==OE_Default then the onError value +** for the constraint is used. +** +** The calling routine must open a read/write cursor for pTab with +** cursor number "baseCur". All indices of pTab must also have open +** read/write cursors with cursor number baseCur+i for the i-th cursor. +** Except, if there is no possibility of a REPLACE action then +** cursors do not need to be open for indices where aRegIdx[i]==0. +*/ +void sqlite3GenerateConstraintChecks( + Parse *pParse, /* The parser context */ + Table *pTab, /* the table into which we are inserting */ + int baseCur, /* Index of a read/write cursor pointing at pTab */ + int regRowid, /* Index of the range of input registers */ + int *aRegIdx, /* Register used by each index. 0 for unused indices */ + int rowidChng, /* True if the rowid might collide with existing entry */ + int isUpdate, /* True for UPDATE, False for INSERT */ + int overrideError, /* Override onError to this if not OE_Default */ + int ignoreDest /* Jump to this label on an OE_Ignore resolution */ +){ + int i; + Vdbe *v; + int nCol; + int onError; + int j1, j2, j3; /* Addresses of jump instructions */ + int regData; /* Register containing first data column */ + int iCur; + Index *pIdx; + int seenReplace = 0; + int hasTwoRowids = (isUpdate && rowidChng); + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ + nCol = pTab->nCol; + regData = regRowid + 1; + + + /* Test all NOT NULL constraints. + */ + for(i=0; iiPKey ){ + continue; + } + onError = pTab->aCol[i].notNull; + if( onError==OE_None ) continue; + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ + onError = OE_Abort; + } + j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i); + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + char *zMsg = 0; + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError); + sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName, + " may not be NULL", (char*)0); + sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC); + break; + } + case OE_Ignore: { + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + break; + } + case OE_Replace: { + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i); + break; + } + } + sqlite3VdbeJumpHere(v, j1); + } + + /* Test all CHECK constraints + */ +#ifndef SQLITE_OMIT_CHECK + if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ + int allOk = sqlite3VdbeMakeLabel(v); + pParse->ckBase = regData; + sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL); + onError = overrideError!=OE_Default ? overrideError : OE_Abort; + if( onError==OE_Ignore ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + }else{ + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError); + } + sqlite3VdbeResolveLabel(v, allOk); + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ + + /* If we have an INTEGER PRIMARY KEY, make sure the primary key + ** of the new record does not previously exist. Except, if this + ** is an UPDATE and the primary key is not changing, that is OK. + */ + if( rowidChng ){ + onError = pTab->keyConf; + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + + if( onError!=OE_Replace || pTab->pIndex ){ + if( isUpdate ){ + j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1); + } + j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid); + switch( onError ){ + default: { + onError = OE_Abort; + /* Fall thru into the next case */ + } + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, + "PRIMARY KEY must be unique", P4_STATIC); + break; + } + case OE_Replace: { + sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0); + seenReplace = 1; + break; + } + case OE_Ignore: { + assert( seenReplace==0 ); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + break; + } + } + sqlite3VdbeJumpHere(v, j3); + if( isUpdate ){ + sqlite3VdbeJumpHere(v, j2); + } + } + } + + /* Test all UNIQUE constraints by creating entries for each UNIQUE + ** index and making sure that duplicate entries do not already exist. + ** Add the new records to the indices as we go. + */ + for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ + int regIdx; + int regR; + + if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */ + + /* Create a key for accessing the index entry */ + regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1); + for(i=0; inColumn; i++){ + int idx = pIdx->aiColumn[i]; + if( idx==pTab->iPKey ){ + sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); + }else{ + sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i); + } + } + sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); + sqlite3IndexAffinityStr(v, pIdx); + sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); + + /* Find out what action to take in case there is an indexing conflict */ + onError = pIdx->onError; + if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( seenReplace ){ + if( onError==OE_Ignore ) onError = OE_Replace; + else if( onError==OE_Fail ) onError = OE_Abort; + } + + + /* Check to see if the new index entry will be unique */ + j2 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdx, 0, pIdx->nColumn); + regR = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR); + j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0, + regR, (char*)aRegIdx[iCur], P4_INT32); + + /* Generate code that executes if the new index entry is not unique */ + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + int j, n1, n2; + char zErrMsg[200]; + sqlite3_snprintf(sizeof(zErrMsg), zErrMsg, + pIdx->nColumn>1 ? "columns " : "column "); + n1 = strlen(zErrMsg); + for(j=0; jnColumn && n1aCol[pIdx->aiColumn[j]].zName; + n2 = strlen(zCol); + if( j>0 ){ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", "); + n1 += 2; + } + if( n1+n2>sizeof(zErrMsg)-30 ){ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "..."); + n1 += 3; + break; + }else{ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol); + n1 += n2; + } + } + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], + pIdx->nColumn>1 ? " are not unique" : " is not unique"); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0); + break; + } + case OE_Ignore: { + assert( seenReplace==0 ); + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + break; + } + case OE_Replace: { + sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0); + seenReplace = 1; + break; + } + } + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeJumpHere(v, j3); + sqlite3ReleaseTempReg(pParse, regR); + } +} + +/* +** This routine generates code to finish the INSERT or UPDATE operation +** that was started by a prior call to sqlite3GenerateConstraintChecks. +** A consecutive range of registers starting at regRowid contains the +** rowid and the content to be inserted. +** +** The arguments to this routine should be the same as the first six +** arguments to sqlite3GenerateConstraintChecks. +*/ +void sqlite3CompleteInsertion( + Parse *pParse, /* The parser context */ + Table *pTab, /* the table into which we are inserting */ + int baseCur, /* Index of a read/write cursor pointing at pTab */ + int regRowid, /* Range of content */ + int *aRegIdx, /* Register used by each index. 0 for unused indices */ + int rowidChng, /* True if the record number will change */ + int isUpdate, /* True for UPDATE, False for INSERT */ + int newIdx, /* Index of NEW table for triggers. -1 if none */ + int appendBias /* True if this is likely to be an append */ +){ + int i; + Vdbe *v; + int nIdx; + Index *pIdx; + int pik_flags; + int regData; + int regRec; + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} + for(i=nIdx-1; i>=0; i--){ + if( aRegIdx[i]==0 ) continue; + sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]); + } + regData = regRowid + 1; + regRec = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); + sqlite3TableAffinityStr(v, pTab); +#ifndef SQLITE_OMIT_TRIGGER + if( newIdx>=0 ){ + sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); + } +#endif + if( pParse->nested ){ + pik_flags = 0; + }else{ + pik_flags = OPFLAG_NCHANGE; + pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); + } + if( appendBias ){ + pik_flags |= OPFLAG_APPEND; + } + sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid); + if( !pParse->nested ){ + sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC); + } + sqlite3VdbeChangeP5(v, pik_flags); +} + +/* +** Generate code that will open cursors for a table and for all +** indices of that table. The "baseCur" parameter is the cursor number used +** for the table. Indices are opened on subsequent cursors. +** +** Return the number of indices on the table. +*/ +int sqlite3OpenTableAndIndices( + Parse *pParse, /* Parsing context */ + Table *pTab, /* Table to be opened */ + int baseCur, /* Cursor number assigned to the table */ + int op /* OP_OpenRead or OP_OpenWrite */ +){ + int i; + int iDb; + Index *pIdx; + Vdbe *v; + + if( IsVirtual(pTab) ) return 0; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + sqlite3OpenTable(pParse, baseCur, iDb, pTab, op); + for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pIdx->zName)); + } + if( pParse->nTab<=baseCur+i ){ + pParse->nTab = baseCur+i; + } + return i-1; +} + + +#ifdef SQLITE_TEST +/* +** The following global variable is incremented whenever the +** transfer optimization is used. This is used for testing +** purposes only - to make sure the transfer optimization really +** is happening when it is suppose to. +*/ +int sqlite3_xferopt_count; +#endif /* SQLITE_TEST */ + + +#ifndef SQLITE_OMIT_XFER_OPT +/* +** Check to collation names to see if they are compatible. +*/ +static int xferCompatibleCollation(const char *z1, const char *z2){ + if( z1==0 ){ + return z2==0; + } + if( z2==0 ){ + return 0; + } + return sqlite3StrICmp(z1, z2)==0; +} + + +/* +** Check to see if index pSrc is compatible as a source of data +** for index pDest in an insert transfer optimization. The rules +** for a compatible index: +** +** * The index is over the same set of columns +** * The same DESC and ASC markings occurs on all columns +** * The same onError processing (OE_Abort, OE_Ignore, etc) +** * The same collating sequence on each column +*/ +static int xferCompatibleIndex(Index *pDest, Index *pSrc){ + int i; + assert( pDest && pSrc ); + assert( pDest->pTable!=pSrc->pTable ); + if( pDest->nColumn!=pSrc->nColumn ){ + return 0; /* Different number of columns */ + } + if( pDest->onError!=pSrc->onError ){ + return 0; /* Different conflict resolution strategies */ + } + for(i=0; inColumn; i++){ + if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ + return 0; /* Different columns indexed */ + } + if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ + return 0; /* Different sort orders */ + } + if( pSrc->azColl[i]!=pDest->azColl[i] ){ + return 0; /* Different collating sequences */ + } + } + + /* If no test above fails then the indices must be compatible */ + return 1; +} + +/* +** Attempt the transfer optimization on INSERTs of the form +** +** INSERT INTO tab1 SELECT * FROM tab2; +** +** This optimization is only attempted if +** +** (1) tab1 and tab2 have identical schemas including all the +** same indices and constraints +** +** (2) tab1 and tab2 are different tables +** +** (3) There must be no triggers on tab1 +** +** (4) The result set of the SELECT statement is "*" +** +** (5) The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY, +** or LIMIT clause. +** +** (6) The SELECT statement is a simple (not a compound) select that +** contains only tab2 in its FROM clause +** +** This method for implementing the INSERT transfers raw records from +** tab2 over to tab1. The columns are not decoded. Raw records from +** the indices of tab2 are transfered to tab1 as well. In so doing, +** the resulting tab1 has much less fragmentation. +** +** This routine returns TRUE if the optimization is attempted. If any +** of the conditions above fail so that the optimization should not +** be attempted, then this routine returns FALSE. +*/ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +){ + 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 */ + struct SrcList_item *pItem; /* An element of pSelect->pSrc */ + int i; /* Loop counter */ + int iDbSrc; /* The database of pSrc */ + int iSrc, iDest; /* Cursors from source and destination */ + int addr1, addr2; /* Loop addresses */ + int emptyDestTest; /* Address of test for empty pDest */ + int emptySrcTest; /* Address of test for empty pSrc */ + Vdbe *v; /* The VDBE we are building */ + KeyInfo *pKey; /* Key information for an index */ + int regAutoinc; /* Memory register used by AUTOINC */ + int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ + int regData, regRowid; /* Registers holding data and rowid */ + + if( pSelect==0 ){ + return 0; /* Must be of the form INSERT INTO ... SELECT ... */ + } + if( pDest->pTrigger ){ + return 0; /* tab1 must not have triggers */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pDest->isVirtual ){ + return 0; /* tab1 must not be a virtual table */ + } +#endif + if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError!=OE_Abort && onError!=OE_Rollback ){ + return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */ + } + assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ + if( pSelect->pSrc->nSrc!=1 ){ + return 0; /* FROM clause must have exactly one term */ + } + if( pSelect->pSrc->a[0].pSelect ){ + return 0; /* FROM clause cannot contain a subquery */ + } + if( pSelect->pWhere ){ + return 0; /* SELECT may not have a WHERE clause */ + } + if( pSelect->pOrderBy ){ + return 0; /* SELECT may not have an ORDER BY clause */ + } + /* Do not need to test for a HAVING clause. If HAVING is present but + ** there is no ORDER BY, we will get an error. */ + if( pSelect->pGroupBy ){ + return 0; /* SELECT may not have a GROUP BY clause */ + } + if( pSelect->pLimit ){ + return 0; /* SELECT may not have a LIMIT clause */ + } + assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ + if( pSelect->pPrior ){ + return 0; /* SELECT may not be a compound query */ + } + if( pSelect->isDistinct ){ + return 0; /* SELECT may not be DISTINCT */ + } + pEList = pSelect->pEList; + assert( pEList!=0 ); + if( pEList->nExpr!=1 ){ + return 0; /* The result set must have exactly one column */ + } + assert( pEList->a[0].pExpr ); + if( pEList->a[0].pExpr->op!=TK_ALL ){ + return 0; /* The result set must be the special operator "*" */ + } + + /* At this point we have established that the statement is of the + ** correct syntactic form to participate in this optimization. Now + ** we have to check the semantics. + */ + pItem = pSelect->pSrc->a; + pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); + if( pSrc==0 ){ + return 0; /* FROM clause does not contain a real table */ + } + if( pSrc==pDest ){ + return 0; /* tab1 and tab2 may not be the same table */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pSrc->isVirtual ){ + return 0; /* tab2 must not be a virtual table */ + } +#endif + if( pSrc->pSelect ){ + return 0; /* tab2 may not be a view */ + } + if( pDest->nCol!=pSrc->nCol ){ + return 0; /* Number of columns must be the same in tab1 and tab2 */ + } + if( pDest->iPKey!=pSrc->iPKey ){ + return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ + } + for(i=0; inCol; i++){ + if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ + return 0; /* Affinity must be the same on all columns */ + } + if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ + return 0; /* Collating sequence must be the same on all columns */ + } + if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ + return 0; /* tab2 must be NOT NULL if tab1 is */ + } + } + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + if( pDestIdx->onError!=OE_None ){ + destHasUniqueIdx = 1; + } + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + if( pSrcIdx==0 ){ + return 0; /* pDestIdx has no corresponding index in pSrc */ + } + } +#ifndef SQLITE_OMIT_CHECK + if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ + return 0; /* Tables have different CHECK constraints. Ticket #2252 */ + } +#endif + + /* If we get this far, it means either: + ** + ** * We can always do the transfer if the table contains an + ** an integer primary key + ** + ** * We can conditionally do the transfer if the destination + ** table is empty. + */ +#ifdef SQLITE_TEST + sqlite3_xferopt_count++; +#endif + iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + v = sqlite3GetVdbe(pParse); + sqlite3CodeVerifySchema(pParse, iDbSrc); + iSrc = pParse->nTab++; + iDest = pParse->nTab++; + regAutoinc = autoIncBegin(pParse, iDbDest, pDest); + sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); + if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ + /* If tables do not have an INTEGER PRIMARY KEY and there + ** are indices to be copied and the destination is not empty, + ** we have to disallow the transfer optimization because the + ** the rowids might change which will mess up indexing. + ** + ** Or if the destination has a UNIQUE index and is not empty, + ** we also disallow the transfer optimization because we cannot + ** insure that all entries in the union of DEST and SRC will be + ** unique. + */ + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0); + emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + }else{ + emptyDestTest = 0; + } + sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); + emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + regData = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + if( pDest->iPKey>=0 ){ + addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, + "PRIMARY KEY must be unique", P4_STATIC); + sqlite3VdbeJumpHere(v, addr2); + autoIncStep(pParse, regAutoinc, regRowid); + }else if( pDest->pIndex==0 ){ + addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid); + }else{ + addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid); + assert( pDest->autoInc==0 ); + } + sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData); + sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid); + sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); + sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); + autoIncEnd(pParse, iDbDest, pDest, regAutoinc); + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + assert( pSrcIdx ); + sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); + sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pSrcIdx->zName)); + pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); + sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest, + (char*)pKey, P4_KEYINFO_HANDOFF); + VdbeComment((v, "%s", pDestIdx->zName)); + addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); + sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData); + sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1); + sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + } + sqlite3VdbeJumpHere(v, emptySrcTest); + sqlite3ReleaseTempReg(pParse, regRowid); + sqlite3ReleaseTempReg(pParse, regData); + sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + if( emptyDestTest ){ + sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0); + sqlite3VdbeJumpHere(v, emptyDestTest); + sqlite3VdbeAddOp2(v, OP_Close, iDest, 0); + return 0; + }else{ + return 1; + } +} +#endif /* SQLITE_OMIT_XFER_OPT */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/journal.c b/client/src/thirdparty/sqlite-3.4.2/src/journal.c new file mode 100644 index 0000000..7cbe5bc --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/journal.c @@ -0,0 +1,238 @@ +/* +** 2007 August 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. +** +************************************************************************* +** +** @(#) $Id: journal.c,v 1.7 2007/09/06 13:49:37 drh Exp $ +*/ + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + +/* +** This file implements a special kind of sqlite3_file object used +** by SQLite to create journal files if the atomic-write optimization +** is enabled. +** +** The distinctive characteristic of this sqlite3_file is that the +** actual on disk file is created lazily. When the file is created, +** the caller specifies a buffer size for an in-memory buffer to +** be used to service read() and write() requests. The actual file +** on disk is not created or populated until either: +** +** 1) The in-memory representation grows too large for the allocated +** buffer, or +** 2) The xSync() method is called. +*/ + +#include "sqliteInt.h" + + +/* +** A JournalFile object is a subclass of sqlite3_file used by +** as an open file handle for journal files. +*/ +struct JournalFile { + sqlite3_io_methods *pMethod; /* I/O methods on journal files */ + int nBuf; /* Size of zBuf[] in bytes */ + char *zBuf; /* Space to buffer journal writes */ + int iSize; /* Amount of zBuf[] currently used */ + int flags; /* xOpen flags */ + sqlite3_vfs *pVfs; /* The "real" underlying VFS */ + sqlite3_file *pReal; /* The "real" underlying file descriptor */ + const char *zJournal; /* Name of the journal file */ +}; +typedef struct JournalFile JournalFile; + +/* +** If it does not already exists, create and populate the on-disk file +** for JournalFile p. +*/ +static int createFile(JournalFile *p){ + int rc = SQLITE_OK; + if( !p->pReal ){ + sqlite3_file *pReal = (sqlite3_file *)&p[1]; + rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0); + if( rc==SQLITE_OK ){ + p->pReal = pReal; + if( p->iSize>0 ){ + assert(p->iSize<=p->nBuf); + rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0); + } + } + } + return rc; +} + +/* +** Close the file. +*/ +static int jrnlClose(sqlite3_file *pJfd){ + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + sqlite3OsClose(p->pReal); + } + sqlite3_free(p->zBuf); + return SQLITE_OK; +} + +/* +** Read data from the file. +*/ +static int jrnlRead( + sqlite3_file *pJfd, /* The journal file from which to read */ + void *zBuf, /* Put the results here */ + int iAmt, /* Number of bytes to read */ + sqlite_int64 iOfst /* Begin reading at this offset */ +){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst); + }else{ + assert( iAmt+iOfst<=p->iSize ); + memcpy(zBuf, &p->zBuf[iOfst], iAmt); + } + return rc; +} + +/* +** Write data to the file. +*/ +static int jrnlWrite( + sqlite3_file *pJfd, /* The journal file into which to write */ + const void *zBuf, /* Take data to be written from here */ + int iAmt, /* Number of bytes to write */ + sqlite_int64 iOfst /* Begin writing at this offset into the file */ +){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( !p->pReal && (iOfst+iAmt)>p->nBuf ){ + rc = createFile(p); + } + if( rc==SQLITE_OK ){ + if( p->pReal ){ + rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst); + }else{ + memcpy(&p->zBuf[iOfst], zBuf, iAmt); + if( p->iSize<(iOfst+iAmt) ){ + p->iSize = (iOfst+iAmt); + } + } + } + return rc; +} + +/* +** Truncate the file. +*/ +static int jrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsTruncate(p->pReal, size); + }else if( sizeiSize ){ + p->iSize = size; + } + return rc; +} + +/* +** Sync the file. +*/ +static int jrnlSync(sqlite3_file *pJfd, int flags){ + int rc; + JournalFile *p = (JournalFile *)pJfd; + rc = createFile(p); + if( rc==SQLITE_OK ){ + rc = sqlite3OsSync(p->pReal, flags); + } + return rc; +} + +/* +** Query the size of the file in bytes. +*/ +static int jrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){ + int rc = SQLITE_OK; + JournalFile *p = (JournalFile *)pJfd; + if( p->pReal ){ + rc = sqlite3OsFileSize(p->pReal, pSize); + }else{ + *pSize = (sqlite_int64) p->iSize; + } + return rc; +} + +/* +** Table of methods for JournalFile sqlite3_file object. +*/ +static struct sqlite3_io_methods JournalFileMethods = { + 1, /* iVersion */ + jrnlClose, /* xClose */ + jrnlRead, /* xRead */ + jrnlWrite, /* xWrite */ + jrnlTruncate, /* xTruncate */ + jrnlSync, /* xSync */ + jrnlFileSize, /* xFileSize */ + 0, /* xLock */ + 0, /* xUnlock */ + 0, /* xCheckReservedLock */ + 0, /* xFileControl */ + 0, /* xSectorSize */ + 0 /* xDeviceCharacteristics */ +}; + +/* +** Open a journal file. +*/ +int sqlite3JournalOpen( + sqlite3_vfs *pVfs, /* The VFS to use for actual file I/O */ + const char *zName, /* Name of the journal file */ + sqlite3_file *pJfd, /* Preallocated, blank file handle */ + int flags, /* Opening flags */ + int nBuf /* Bytes buffered before opening the file */ +){ + JournalFile *p = (JournalFile *)pJfd; + memset(p, 0, sqlite3JournalSize(pVfs)); + if( nBuf>0 ){ + p->zBuf = sqlite3MallocZero(nBuf); + if( !p->zBuf ){ + return SQLITE_NOMEM; + } + }else{ + return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0); + } + p->pMethod = &JournalFileMethods; + p->nBuf = nBuf; + p->flags = flags; + p->zJournal = zName; + p->pVfs = pVfs; + return SQLITE_OK; +} + +/* +** If the argument p points to a JournalFile structure, and the underlying +** file has not yet been created, create it now. +*/ +int sqlite3JournalCreate(sqlite3_file *p){ + if( p->pMethods!=&JournalFileMethods ){ + return SQLITE_OK; + } + return createFile((JournalFile *)p); +} + +/* +** Return the number of bytes required to store a JournalFile that uses vfs +** pVfs to create the underlying on-disk files. +*/ +int sqlite3JournalSize(sqlite3_vfs *pVfs){ + return (pVfs->szOsFile+sizeof(JournalFile)); +} +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/legacy.c b/client/src/thirdparty/sqlite-3.4.2/src/legacy.c new file mode 100644 index 0000000..c004b89 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/legacy.c @@ -0,0 +1,134 @@ +/* +** 2001 September 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. +** +************************************************************************* +** Main file for the SQLite library. The routines in this file +** implement the programmer interface to the library. Routines in +** other files are for internal use by SQLite and should not be +** accessed by users of the library. +** +** $Id: legacy.c,v 1.22 2007/08/29 12:31:26 danielk1977 Exp $ +*/ + +#include "sqliteInt.h" +#include + +/* +** Execute SQL code. Return one of the SQLITE_ success/failure +** codes. Also write an error message into memory obtained from +** malloc() and make *pzErrMsg point to that message. +** +** If the SQL is a query, then for each row in the query result +** the xCallback() function is called. pArg becomes the first +** argument to xCallback(). If xCallback=NULL then no callback +** is invoked, even for queries. +*/ +int sqlite3_exec( + sqlite3 *db, /* The database on which the SQL executes */ + const char *zSql, /* The SQL to be executed */ + sqlite3_callback xCallback, /* Invoke this callback routine */ + void *pArg, /* First argument to xCallback() */ + char **pzErrMsg /* Write error messages here */ +){ + int rc = SQLITE_OK; + const char *zLeftover; + sqlite3_stmt *pStmt = 0; + char **azCols = 0; + + int nRetry = 0; + int nCallback; + + if( zSql==0 ) return SQLITE_OK; + + sqlite3_mutex_enter(db->mutex); + while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){ + int nCol; + char **azVals = 0; + + pStmt = 0; + rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover); + assert( rc==SQLITE_OK || pStmt==0 ); + if( rc!=SQLITE_OK ){ + continue; + } + if( !pStmt ){ + /* this happens for a comment or white-space */ + zSql = zLeftover; + continue; + } + + nCallback = 0; + + nCol = sqlite3_column_count(pStmt); + azCols = sqlite3DbMallocZero(db, 2*nCol*sizeof(const char *) + 1); + if( azCols==0 ){ + goto exec_out; + } + + while( 1 ){ + int i; + rc = sqlite3_step(pStmt); + + /* Invoke the callback function if required */ + if( xCallback && (SQLITE_ROW==rc || + (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){ + if( 0==nCallback ){ + for(i=0; ierrMask)==rc ); + sqlite3_mutex_leave(db->mutex); + return rc; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/limits.h b/client/src/thirdparty/sqlite-3.4.2/src/limits.h new file mode 100644 index 0000000..fc31f34 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/limits.h @@ -0,0 +1,158 @@ +/* +** 2007 May 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file defines various limits of what SQLite can process. +** +** @(#) $Id: limits.h,v 1.9 2007/06/09 09:53:51 drh Exp $ +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** The hard limit here is the same as SQLITE_MAX_LENGTH. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. A value of 0 (the default) means do not enforce +** any limitation on expression tree depth. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 100 +#endif + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +*/ +#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 maximum number of attached databases. This must be at least 2 +** in order to support the main database file (0) and the file used to +** hold temporary tables (1). And it must be less than 32 because +** we use a bitmask of databases with a u32 in places (for example +** the Parse.cookieMask field). +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif + +/* Maximum page size. The upper bound on this value is 32768. This a limit +** imposed by the necessity of storing the value in a 2-byte unsigned integer +** and the fact that the page size must be a power of 2. +*/ +#ifndef SQLITE_MAX_PAGE_SIZE +# define SQLITE_MAX_PAGE_SIZE 32768 +#endif + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/loadext.c b/client/src/thirdparty/sqlite-3.4.2/src/loadext.c new file mode 100644 index 0000000..8293486 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/loadext.c @@ -0,0 +1,518 @@ +/* +** 2006 June 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code used to dynamically load extensions into +** the SQLite library. +*/ +#ifndef SQLITE_OMIT_LOAD_EXTENSION + +#ifndef SQLITE_CORE + #define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */ +#endif +#include "sqlite3ext.h" +#include "sqliteInt.h" +#include +#include + +/* +** Some API routines are omitted when various features are +** excluded from a build of SQLite. Substitute a NULL pointer +** for any missing APIs. +*/ +#ifndef SQLITE_ENABLE_COLUMN_METADATA +# define sqlite3_column_database_name 0 +# define sqlite3_column_database_name16 0 +# define sqlite3_column_table_name 0 +# define sqlite3_column_table_name16 0 +# define sqlite3_column_origin_name 0 +# define sqlite3_column_origin_name16 0 +# define sqlite3_table_column_metadata 0 +#endif + +#ifdef SQLITE_OMIT_AUTHORIZATION +# define sqlite3_set_authorizer 0 +#endif + +#ifdef SQLITE_OMIT_UTF16 +# define sqlite3_bind_text16 0 +# define sqlite3_collation_needed16 0 +# define sqlite3_column_decltype16 0 +# define sqlite3_column_name16 0 +# define sqlite3_column_text16 0 +# define sqlite3_complete16 0 +# define sqlite3_create_collation16 0 +# define sqlite3_create_function16 0 +# define sqlite3_errmsg16 0 +# define sqlite3_open16 0 +# define sqlite3_prepare16 0 +# define sqlite3_prepare16_v2 0 +# define sqlite3_result_error16 0 +# define sqlite3_result_text16 0 +# define sqlite3_result_text16be 0 +# define sqlite3_result_text16le 0 +# define sqlite3_value_text16 0 +# define sqlite3_value_text16be 0 +# define sqlite3_value_text16le 0 +# define sqlite3_column_database_name16 0 +# define sqlite3_column_table_name16 0 +# define sqlite3_column_origin_name16 0 +#endif + +#ifdef SQLITE_OMIT_COMPLETE +# define sqlite3_complete 0 +# define sqlite3_complete16 0 +#endif + +#ifdef SQLITE_OMIT_PROGRESS_CALLBACK +# define sqlite3_progress_handler 0 +#endif + +#ifdef SQLITE_OMIT_VIRTUALTABLE +# define sqlite3_create_module 0 +# define sqlite3_create_module_v2 0 +# define sqlite3_declare_vtab 0 +#endif + +#ifdef SQLITE_OMIT_SHARED_CACHE +# define sqlite3_enable_shared_cache 0 +#endif + +#ifdef SQLITE_OMIT_TRACE +# define sqlite3_profile 0 +# define sqlite3_trace 0 +#endif + +#ifdef SQLITE_OMIT_GET_TABLE +# define sqlite3_free_table 0 +# define sqlite3_get_table 0 +#endif + +#ifdef SQLITE_OMIT_INCRBLOB +#define sqlite3_bind_zeroblob 0 +#define sqlite3_blob_bytes 0 +#define sqlite3_blob_close 0 +#define sqlite3_blob_open 0 +#define sqlite3_blob_read 0 +#define sqlite3_blob_write 0 +#endif + +/* +** The following structure contains pointers to all SQLite API routines. +** A pointer to this structure is passed into extensions when they are +** loaded so that the extension can make calls back into the SQLite +** library. +** +** When adding new APIs, add them to the bottom of this structure +** in order to preserve backwards compatibility. +** +** Extensions that use newer APIs should first call the +** sqlite3_libversion_number() to make sure that the API they +** intend to use is supported by the library. Extensions should +** also check to make sure that the pointer to the function is +** not NULL before calling it. +*/ +const sqlite3_api_routines sqlite3_apis = { + sqlite3_aggregate_context, + sqlite3_aggregate_count, + sqlite3_bind_blob, + sqlite3_bind_double, + sqlite3_bind_int, + sqlite3_bind_int64, + sqlite3_bind_null, + sqlite3_bind_parameter_count, + sqlite3_bind_parameter_index, + sqlite3_bind_parameter_name, + sqlite3_bind_text, + sqlite3_bind_text16, + sqlite3_bind_value, + sqlite3_busy_handler, + sqlite3_busy_timeout, + sqlite3_changes, + sqlite3_close, + sqlite3_collation_needed, + sqlite3_collation_needed16, + sqlite3_column_blob, + sqlite3_column_bytes, + sqlite3_column_bytes16, + sqlite3_column_count, + sqlite3_column_database_name, + sqlite3_column_database_name16, + sqlite3_column_decltype, + sqlite3_column_decltype16, + sqlite3_column_double, + sqlite3_column_int, + sqlite3_column_int64, + sqlite3_column_name, + sqlite3_column_name16, + sqlite3_column_origin_name, + sqlite3_column_origin_name16, + sqlite3_column_table_name, + sqlite3_column_table_name16, + sqlite3_column_text, + sqlite3_column_text16, + sqlite3_column_type, + sqlite3_column_value, + sqlite3_commit_hook, + sqlite3_complete, + sqlite3_complete16, + sqlite3_create_collation, + sqlite3_create_collation16, + sqlite3_create_function, + sqlite3_create_function16, + sqlite3_create_module, + sqlite3_data_count, + sqlite3_db_handle, + sqlite3_declare_vtab, + sqlite3_enable_shared_cache, + sqlite3_errcode, + sqlite3_errmsg, + sqlite3_errmsg16, + sqlite3_exec, + sqlite3_expired, + sqlite3_finalize, + sqlite3_free, + sqlite3_free_table, + sqlite3_get_autocommit, + sqlite3_get_auxdata, + sqlite3_get_table, + 0, /* Was sqlite3_global_recover(), but that function is deprecated */ + sqlite3_interrupt, + sqlite3_last_insert_rowid, + sqlite3_libversion, + sqlite3_libversion_number, + sqlite3_malloc, + sqlite3_mprintf, + sqlite3_open, + sqlite3_open16, + sqlite3_prepare, + sqlite3_prepare16, + sqlite3_profile, + sqlite3_progress_handler, + sqlite3_realloc, + sqlite3_reset, + sqlite3_result_blob, + sqlite3_result_double, + sqlite3_result_error, + sqlite3_result_error16, + sqlite3_result_int, + sqlite3_result_int64, + sqlite3_result_null, + sqlite3_result_text, + sqlite3_result_text16, + sqlite3_result_text16be, + sqlite3_result_text16le, + sqlite3_result_value, + sqlite3_rollback_hook, + sqlite3_set_authorizer, + sqlite3_set_auxdata, + sqlite3_snprintf, + sqlite3_step, + sqlite3_table_column_metadata, + sqlite3_thread_cleanup, + sqlite3_total_changes, + sqlite3_trace, + sqlite3_transfer_bindings, + sqlite3_update_hook, + sqlite3_user_data, + sqlite3_value_blob, + sqlite3_value_bytes, + sqlite3_value_bytes16, + sqlite3_value_double, + sqlite3_value_int, + sqlite3_value_int64, + sqlite3_value_numeric_type, + sqlite3_value_text, + sqlite3_value_text16, + sqlite3_value_text16be, + sqlite3_value_text16le, + sqlite3_value_type, + sqlite3_vmprintf, + /* + ** The original API set ends here. All extensions can call any + ** of the APIs above provided that the pointer is not NULL. But + ** before calling APIs that follow, extension should check the + ** sqlite3_libversion_number() to make sure they are dealing with + ** a library that is new enough to support that API. + ************************************************************************* + */ + sqlite3_overload_function, + + /* + ** Added after 3.3.13 + */ + sqlite3_prepare_v2, + sqlite3_prepare16_v2, + sqlite3_clear_bindings, + + /* + ** Added for 3.4.1 + */ + sqlite3_create_module_v2, + + /* + ** Added for 3.5.0 + */ + sqlite3_bind_zeroblob, + sqlite3_blob_bytes, + sqlite3_blob_close, + sqlite3_blob_open, + sqlite3_blob_read, + sqlite3_blob_write, + sqlite3_create_collation_v2, + sqlite3_file_control, + sqlite3_memory_highwater, + sqlite3_memory_used, +#ifdef SQLITE_MUTEX_NOOP + 0, + 0, + 0, + 0, + 0, +#else + sqlite3_mutex_alloc, + sqlite3_mutex_enter, + sqlite3_mutex_free, + sqlite3_mutex_leave, + sqlite3_mutex_try, +#endif + sqlite3_open_v2, + sqlite3_release_memory, + sqlite3_result_error_nomem, + sqlite3_result_error_toobig, + sqlite3_sleep, + sqlite3_soft_heap_limit, + sqlite3_vfs_find, + sqlite3_vfs_register, + sqlite3_vfs_unregister, +}; + +/* +** Attempt to load an SQLite extension library contained in the file +** zFile. The entry point is zProc. zProc may be 0 in which case a +** default entry point name (sqlite3_extension_init) is used. Use +** of the default name is recommended. +** +** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong. +** +** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with +** error message text. The calling function should free this memory +** by calling sqlite3_free(). +*/ +static int sqlite3LoadExtension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +){ + sqlite3_vfs *pVfs = db->pVfs; + void *handle; + int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*); + char *zErrmsg = 0; + void **aHandle; + + /* Ticket #1863. To avoid a creating security problems for older + ** applications that relink against newer versions of SQLite, the + ** ability to run load_extension is turned off by default. One + ** must call sqlite3_enable_load_extension() to turn on extension + ** loading. Otherwise you get the following error. + */ + if( (db->flags & SQLITE_LoadExtension)==0 ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("not authorized"); + } + return SQLITE_ERROR; + } + + if( zProc==0 ){ + zProc = "sqlite3_extension_init"; + } + + handle = sqlite3OsDlOpen(pVfs, zFile); + if( handle==0 ){ + if( pzErrMsg ){ + char zErr[256]; + zErr[sizeof(zErr)-1] = '\0'; + sqlite3_snprintf(sizeof(zErr)-1, zErr, + "unable to open shared library [%s]", zFile); + sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); + *pzErrMsg = sqlite3DbStrDup(db, zErr); + } + return SQLITE_ERROR; + } + xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) + sqlite3OsDlSym(pVfs, handle, zProc); + if( xInit==0 ){ + if( pzErrMsg ){ + char zErr[256]; + zErr[sizeof(zErr)-1] = '\0'; + sqlite3_snprintf(sizeof(zErr)-1, zErr, + "no entry point [%s] in shared library [%s]", zProc,zFile); + sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr); + *pzErrMsg = sqlite3DbStrDup(db, zErr); + sqlite3OsDlClose(pVfs, handle); + } + return SQLITE_ERROR; + }else if( xInit(db, &zErrmsg, &sqlite3_apis) ){ + if( pzErrMsg ){ + *pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg); + } + sqlite3_free(zErrmsg); + sqlite3OsDlClose(pVfs, handle); + return SQLITE_ERROR; + } + + /* Append the new shared library handle to the db->aExtension array. */ + db->nExtension++; + aHandle = sqlite3DbMallocZero(db, sizeof(handle)*db->nExtension); + if( aHandle==0 ){ + return SQLITE_NOMEM; + } + if( db->nExtension>0 ){ + memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1)); + } + sqlite3_free(db->aExtension); + db->aExtension = aHandle; + + db->aExtension[db->nExtension-1] = handle; + return SQLITE_OK; +} +int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +){ + int rc; + sqlite3_mutex_enter(db->mutex); + rc = sqlite3LoadExtension(db, zFile, zProc, pzErrMsg); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Call this routine when the database connection is closing in order +** to clean up loaded extensions +*/ +void sqlite3CloseExtensions(sqlite3 *db){ + int i; + assert( sqlite3_mutex_held(db->mutex) ); + for(i=0; inExtension; i++){ + sqlite3OsDlClose(db->pVfs, db->aExtension[i]); + } + sqlite3_free(db->aExtension); +} + +/* +** Enable or disable extension loading. Extension loading is disabled by +** default so as not to open security holes in older applications. +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff){ + sqlite3_mutex_enter(db->mutex); + if( onoff ){ + db->flags |= SQLITE_LoadExtension; + }else{ + db->flags &= ~SQLITE_LoadExtension; + } + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +/* +** The following object holds the list of automatically loaded +** extensions. +** +** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER +** mutex must be held while accessing this list. +*/ +static struct { + int nExt; /* Number of entries in aExt[] */ + void **aExt; /* Pointers to the extension init functions */ +} autoext = { 0, 0 }; + + +/* +** Register a statically linked extension that is automatically +** loaded by every new database connection. +*/ +int sqlite3_auto_extension(void *xInit){ + int i; + int rc = SQLITE_OK; + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); + sqlite3_mutex_enter(mutex); + for(i=0; i=autoext.nExt ){ + xInit = 0; + go = 0; + }else{ + xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*)) + autoext.aExt[i]; + } + sqlite3_mutex_leave(mutex); + if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){ + sqlite3Error(db, SQLITE_ERROR, + "automatic extension loading failed: %s", zErrmsg); + go = 0; + rc = SQLITE_ERROR; + sqlite3_free(zErrmsg); + } + } + return rc; +} + +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/main.c b/client/src/thirdparty/sqlite-3.4.2/src/main.c new file mode 100644 index 0000000..5f878f0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/main.c @@ -0,0 +1,1509 @@ +/* +** 2001 September 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. +** +************************************************************************* +** Main file for the SQLite library. The routines in this file +** implement the programmer interface to the library. Routines in +** other files are for internal use by SQLite and should not be +** accessed by users of the library. +** +** $Id: main.c,v 1.417 2008/01/31 15:31:02 danielk1977 Exp $ +*/ +#include "sqliteInt.h" +#include +#ifdef SQLITE_ENABLE_FTS3 +# include "fts3.h" +#endif + +/* +** The version of the library +*/ +const char sqlite3_version[] = SQLITE_VERSION; +const char *sqlite3_libversion(void){ return sqlite3_version; } +int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } +int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; } + +/* +** If the following function pointer is not NULL and if +** SQLITE_ENABLE_IOTRACE is enabled, then messages describing +** I/O active are written using this function. These messages +** are intended for debugging activity only. +*/ +void (*sqlite3_io_trace)(const char*, ...) = 0; + +/* +** If the following global variable points to a string which is the +** name of a directory, then that directory will be used to store +** temporary files. +** +** See also the "PRAGMA temp_store_directory" SQL command. +*/ +char *sqlite3_temp_directory = 0; + + +/* +** Return true if the buffer z[0..n-1] contains all spaces. +*/ +static int allSpaces(const char *z, int n){ + while( n>0 && z[--n]==' ' ){} + return n==0; +} + +/* +** This is the default collating function named "BINARY" which is always +** available. +** +** If the padFlag argument is not NULL then space padding at the end +** of strings is ignored. This implements the RTRIM collation. +*/ +static int binCollFunc( + void *padFlag, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int rc, n; + n = nKey1lastRowid; +} + +/* +** Return the number of changes in the most recent call to sqlite3_exec(). +*/ +int sqlite3_changes(sqlite3 *db){ + return db->nChange; +} + +/* +** Return the number of changes since the database handle was opened. +*/ +int sqlite3_total_changes(sqlite3 *db){ + return db->nTotalChange; +} + +/* +** Close an existing SQLite database +*/ +int sqlite3_close(sqlite3 *db){ + HashElem *i; + int j; + + if( !db ){ + return SQLITE_OK; + } + if( !sqlite3SafetyCheckSickOrOk(db) ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(db->mutex); + +#ifdef SQLITE_SSE + { + extern void sqlite3SseCleanup(sqlite3*); + sqlite3SseCleanup(db); + } +#endif + + sqlite3ResetInternalSchema(db, 0); + + /* If a transaction is open, the ResetInternalSchema() call above + ** will not have called the xDisconnect() method on any virtual + ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() + ** call will do so. We need to do this before the check for active + ** SQL statements below, as the v-table implementation may be storing + ** some prepared statements internally. + */ + sqlite3VtabRollback(db); + + /* If there are any outstanding VMs, return SQLITE_BUSY. */ + if( db->pVdbe ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to close due to unfinalised statements"); + sqlite3_mutex_leave(db->mutex); + return SQLITE_BUSY; + } + assert( sqlite3SafetyCheckSickOrOk(db) ); + + for(j=0; jnDb; j++){ + struct Db *pDb = &db->aDb[j]; + if( pDb->pBt ){ + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + if( j!=1 ){ + pDb->pSchema = 0; + } + } + } + sqlite3ResetInternalSchema(db, 0); + assert( db->nDb<=2 ); + assert( db->aDb==db->aDbStatic ); + for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ + FuncDef *pFunc, *pNext; + for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ + pNext = pFunc->pNext; + sqlite3_free(pFunc); + } + } + + for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(i); + /* Invoke any destructors registered for collation sequence user data. */ + for(j=0; j<3; j++){ + if( pColl[j].xDel ){ + pColl[j].xDel(pColl[j].pUser); + } + } + sqlite3_free(pColl); + } + sqlite3HashClear(&db->aCollSeq); +#ifndef SQLITE_OMIT_VIRTUALTABLE + for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ + Module *pMod = (Module *)sqliteHashData(i); + if( pMod->xDestroy ){ + pMod->xDestroy(pMod->pAux); + } + sqlite3_free(pMod); + } + sqlite3HashClear(&db->aModule); +#endif + + sqlite3HashClear(&db->aFunc); + sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ + if( db->pErr ){ + sqlite3ValueFree(db->pErr); + } + sqlite3CloseExtensions(db); + + db->magic = SQLITE_MAGIC_ERROR; + + /* The temp-database schema is allocated differently from the other schema + ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). + ** So it needs to be freed here. Todo: Why not roll the temp schema into + ** the same sqliteMalloc() as the one that allocates the database + ** structure? + */ + sqlite3_free(db->aDb[1].pSchema); + sqlite3_mutex_leave(db->mutex); + db->magic = SQLITE_MAGIC_CLOSED; + sqlite3_mutex_free(db->mutex); + sqlite3_free(db); + return SQLITE_OK; +} + +/* +** Rollback all database files. +*/ +void sqlite3RollbackAll(sqlite3 *db){ + int i; + int inTrans = 0; + assert( sqlite3_mutex_held(db->mutex) ); + sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1); + for(i=0; inDb; i++){ + if( db->aDb[i].pBt ){ + if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + inTrans = 1; + } + sqlite3BtreeRollback(db->aDb[i].pBt); + db->aDb[i].inTrans = 0; + } + } + sqlite3VtabRollback(db); + sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + + if( db->flags&SQLITE_InternChanges ){ + sqlite3ExpirePreparedStatements(db); + sqlite3ResetInternalSchema(db, 0); + } + + /* If one has been configured, invoke the rollback-hook callback */ + if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ + db->xRollbackCallback(db->pRollbackArg); + } +} + +/* +** Return a static string that describes the kind of error specified in the +** argument. +*/ +const char *sqlite3ErrStr(int rc){ + const char *z; + switch( rc & 0xff ){ + case SQLITE_ROW: + case SQLITE_DONE: + case SQLITE_OK: z = "not an error"; break; + case SQLITE_ERROR: z = "SQL logic error or missing database"; break; + case SQLITE_PERM: z = "access permission denied"; break; + case SQLITE_ABORT: z = "callback requested query abort"; break; + case SQLITE_BUSY: z = "database is locked"; break; + case SQLITE_LOCKED: z = "database table is locked"; break; + case SQLITE_NOMEM: z = "out of memory"; break; + case SQLITE_READONLY: z = "attempt to write a readonly database"; break; + case SQLITE_INTERRUPT: z = "interrupted"; break; + case SQLITE_IOERR: z = "disk I/O error"; break; + case SQLITE_CORRUPT: z = "database disk image is malformed"; break; + case SQLITE_FULL: z = "database or disk is full"; break; + case SQLITE_CANTOPEN: z = "unable to open database file"; break; + case SQLITE_EMPTY: z = "table contains no data"; break; + case SQLITE_SCHEMA: z = "database schema has changed"; break; + case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break; + case SQLITE_CONSTRAINT: z = "constraint failed"; break; + case SQLITE_MISMATCH: z = "datatype mismatch"; break; + case SQLITE_MISUSE: z = "library routine called out of sequence";break; + case SQLITE_NOLFS: z = "kernel lacks large file support"; break; + case SQLITE_AUTH: z = "authorization denied"; break; + case SQLITE_FORMAT: z = "auxiliary database format error"; break; + case SQLITE_RANGE: z = "bind or column index out of range"; break; + case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; + default: z = "unknown error"; break; + } + return z; +} + +/* +** This routine implements a busy callback that sleeps and tries +** again until a timeout value is reached. The timeout value is +** an integer number of milliseconds passed in as the first +** argument. +*/ +static int sqliteDefaultBusyCallback( + void *ptr, /* Database connection */ + int count /* Number of times table has been busy */ +){ +#if OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP) + static const u8 delays[] = + { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; + static const u8 totals[] = + { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; +# define NDELAY (sizeof(delays)/sizeof(delays[0])) + sqlite3 *db = (sqlite3 *)ptr; + int timeout = db->busyTimeout; + int delay, prior; + + assert( count>=0 ); + if( count < NDELAY ){ + delay = delays[count]; + prior = totals[count]; + }else{ + delay = delays[NDELAY-1]; + prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); + } + if( prior + delay > timeout ){ + delay = timeout - prior; + if( delay<=0 ) return 0; + } + sqlite3OsSleep(db->pVfs, delay*1000); + return 1; +#else + sqlite3 *db = (sqlite3 *)ptr; + int timeout = ((sqlite3 *)ptr)->busyTimeout; + if( (count+1)*1000 > timeout ){ + return 0; + } + sqlite3OsSleep(db->pVfs, 1000000); + return 1; +#endif +} + +/* +** Invoke the given busy handler. +** +** This routine is called when an operation failed with a lock. +** If this routine returns non-zero, the lock is retried. If it +** returns 0, the operation aborts with an SQLITE_BUSY error. +*/ +int sqlite3InvokeBusyHandler(BusyHandler *p){ + int rc; + if( p==0 || p->xFunc==0 || p->nBusy<0 ) return 0; + rc = p->xFunc(p->pArg, p->nBusy); + if( rc==0 ){ + p->nBusy = -1; + }else{ + p->nBusy++; + } + return rc; +} + +/* +** This routine sets the busy callback for an Sqlite database to the +** given callback function with the given argument. +*/ +int sqlite3_busy_handler( + sqlite3 *db, + int (*xBusy)(void*,int), + void *pArg +){ + sqlite3_mutex_enter(db->mutex); + db->busyHandler.xFunc = xBusy; + db->busyHandler.pArg = pArg; + db->busyHandler.nBusy = 0; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +/* +** This routine sets the progress callback for an Sqlite database to the +** given callback function with the given argument. The progress callback will +** be invoked every nOps opcodes. +*/ +void sqlite3_progress_handler( + sqlite3 *db, + int nOps, + int (*xProgress)(void*), + void *pArg +){ + if( sqlite3SafetyCheckOk(db) ){ + sqlite3_mutex_enter(db->mutex); + if( nOps>0 ){ + db->xProgress = xProgress; + db->nProgressOps = nOps; + db->pProgressArg = pArg; + }else{ + db->xProgress = 0; + db->nProgressOps = 0; + db->pProgressArg = 0; + } + sqlite3_mutex_leave(db->mutex); + } +} +#endif + + +/* +** This routine installs a default busy handler that waits for the +** specified number of milliseconds before returning 0. +*/ +int sqlite3_busy_timeout(sqlite3 *db, int ms){ + if( ms>0 ){ + db->busyTimeout = ms; + sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); + }else{ + sqlite3_busy_handler(db, 0, 0); + } + return SQLITE_OK; +} + +/* +** Cause any pending operation to stop at its earliest opportunity. +*/ +void sqlite3_interrupt(sqlite3 *db){ + if( sqlite3SafetyCheckOk(db) ){ + db->u1.isInterrupted = 1; + } +} + + +/* +** This function is exactly the same as sqlite3_create_function(), except +** that it is designed to be called by internal code. The difference is +** that if a malloc() fails in sqlite3_create_function(), an error code +** is returned and the mallocFailed flag cleared. +*/ +int sqlite3CreateFunc( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *pUserData, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + FuncDef *p; + int nName; + + assert( sqlite3_mutex_held(db->mutex) ); + if( zFunctionName==0 || + (xFunc && (xFinal || xStep)) || + (!xFunc && (xFinal && !xStep)) || + (!xFunc && (!xFinal && xStep)) || + (nArg<-1 || nArg>127) || + (255<(nName = strlen(zFunctionName))) ){ + sqlite3Error(db, SQLITE_ERROR, "bad parameters"); + return SQLITE_ERROR; + } + +#ifndef SQLITE_OMIT_UTF16 + /* If SQLITE_UTF16 is specified as the encoding type, transform this + ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the + ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. + ** + ** If SQLITE_ANY is specified, add three versions of the function + ** to the hash table. + */ + if( enc==SQLITE_UTF16 ){ + enc = SQLITE_UTF16NATIVE; + }else if( enc==SQLITE_ANY ){ + int rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, + pUserData, xFunc, xStep, xFinal); + if( rc==SQLITE_OK ){ + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, + pUserData, xFunc, xStep, xFinal); + } + if( rc!=SQLITE_OK ){ + return rc; + } + enc = SQLITE_UTF16BE; + } +#else + enc = SQLITE_UTF8; +#endif + + /* Check if an existing function is being overridden or deleted. If so, + ** and there are active VMs, then return SQLITE_BUSY. If a function + ** is being overridden/deleted but there are no active VMs, allow the + ** operation to continue but invalidate all precompiled statements. + */ + p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0); + if( p && p->iPrefEnc==enc && p->nArg==nArg ){ + if( db->activeVdbeCnt ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to delete/modify user-function due to active statements"); + assert( !db->mallocFailed ); + return SQLITE_BUSY; + }else{ + sqlite3ExpirePreparedStatements(db); + } + } + + p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); + assert(p || db->mallocFailed); + if( !p ){ + return SQLITE_NOMEM; + } + p->flags = 0; + p->xFunc = xFunc; + p->xStep = xStep; + p->xFinalize = xFinal; + p->pUserData = pUserData; + p->nArg = nArg; + return SQLITE_OK; +} + +/* +** Create new user functions. +*/ +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + int rc; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#ifndef SQLITE_OMIT_UTF16 +int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +){ + int rc; + char *zFunc8; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1); + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); + sqlite3_free(zFunc8); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} +#endif + + +/* +** Declare that a function has been overloaded by a virtual table. +** +** If the function already exists as a regular global function, then +** this routine is a no-op. If the function does not exist, then create +** a new one that always throws a run-time error. +** +** When virtual tables intend to provide an overloaded function, they +** should call this routine to make sure the global function exists. +** A global function must exist in order for name resolution to work +** properly. +*/ +int sqlite3_overload_function( + sqlite3 *db, + const char *zName, + int nArg +){ + int nName = strlen(zName); + int rc; + sqlite3_mutex_enter(db->mutex); + if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ + sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, + 0, sqlite3InvalidFunction, 0, 0); + } + rc = sqlite3ApiExit(db, SQLITE_OK); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#ifndef SQLITE_OMIT_TRACE +/* +** Register a trace function. The pArg from the previously registered trace +** is returned. +** +** A NULL trace function means that no tracing is executes. A non-NULL +** trace is a pointer to a function that is invoked at the start of each +** SQL statement. +*/ +void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pTraceArg; + db->xTrace = xTrace; + db->pTraceArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pOld; +} +/* +** Register a profile function. The pArg from the previously registered +** profile function is returned. +** +** A NULL profile function means that no profiling is executes. A non-NULL +** profile is a pointer to a function that is invoked at the conclusion of +** each SQL statement that is run. +*/ +void *sqlite3_profile( + sqlite3 *db, + void (*xProfile)(void*,const char*,sqlite_uint64), + void *pArg +){ + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pProfileArg; + db->xProfile = xProfile; + db->pProfileArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pOld; +} +#endif /* SQLITE_OMIT_TRACE */ + +/*** EXPERIMENTAL *** +** +** Register a function to be invoked when a transaction comments. +** If the invoked function returns non-zero, then the commit becomes a +** rollback. +*/ +void *sqlite3_commit_hook( + sqlite3 *db, /* Attach the hook to this database */ + int (*xCallback)(void*), /* Function to invoke on each commit */ + void *pArg /* Argument to the function */ +){ + void *pOld; + sqlite3_mutex_enter(db->mutex); + pOld = db->pCommitArg; + db->xCommitCallback = xCallback; + db->pCommitArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pOld; +} + +/* +** Register a callback to be invoked each time a row is updated, +** inserted or deleted using this database connection. +*/ +void *sqlite3_update_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), + void *pArg /* Argument to the function */ +){ + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pUpdateArg; + db->xUpdateCallback = xCallback; + db->pUpdateArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} + +/* +** Register a callback to be invoked each time a transaction is rolled +** back by this database connection. +*/ +void *sqlite3_rollback_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*), /* Callback function */ + void *pArg /* Argument to the function */ +){ + void *pRet; + sqlite3_mutex_enter(db->mutex); + pRet = db->pRollbackArg; + db->xRollbackCallback = xCallback; + db->pRollbackArg = pArg; + sqlite3_mutex_leave(db->mutex); + return pRet; +} + +/* +** This routine is called to create a connection to a database BTree +** driver. If zFilename is the name of a file, then that file is +** opened and used. If zFilename is the magic name ":memory:" then +** the database is stored in memory (and is thus forgotten as soon as +** the connection is closed.) If zFilename is NULL then the database +** is a "virtual" database for transient use only and is deleted as +** soon as the connection is closed. +** +** A virtual database can be either a disk file (that is automatically +** deleted when the file is closed) or it an be held entirely in memory, +** depending on the values of the TEMP_STORE compile-time macro and the +** db->temp_store variable, according to the following chart: +** +** TEMP_STORE db->temp_store Location of temporary database +** ---------- -------------- ------------------------------ +** 0 any file +** 1 1 file +** 1 2 memory +** 1 0 file +** 2 1 file +** 2 2 memory +** 2 0 memory +** 3 any memory +*/ +int sqlite3BtreeFactory( + const sqlite3 *db, /* Main database when opening aux otherwise 0 */ + const char *zFilename, /* Name of the file containing the BTree database */ + int omitJournal, /* if TRUE then do not journal this file */ + int nCache, /* How many pages in the page cache */ + int vfsFlags, /* Flags passed through to vfsOpen */ + Btree **ppBtree /* Pointer to new Btree object written here */ +){ + int btFlags = 0; + int rc; + + assert( sqlite3_mutex_held(db->mutex) ); + assert( ppBtree != 0); + if( omitJournal ){ + btFlags |= BTREE_OMIT_JOURNAL; + } + if( db->flags & SQLITE_NoReadlock ){ + btFlags |= BTREE_NO_READLOCK; + } + if( zFilename==0 ){ +#if TEMP_STORE==0 + /* Do nothing */ +#endif +#ifndef SQLITE_OMIT_MEMORYDB +#if TEMP_STORE==1 + if( db->temp_store==2 ) zFilename = ":memory:"; +#endif +#if TEMP_STORE==2 + if( db->temp_store!=1 ) zFilename = ":memory:"; +#endif +#if TEMP_STORE==3 + zFilename = ":memory:"; +#endif +#endif /* SQLITE_OMIT_MEMORYDB */ + } + + if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ + vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; + } + rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); + if( rc==SQLITE_OK ){ + sqlite3BtreeSetCacheSize(*ppBtree, nCache); + } + return rc; +} + +/* +** Return UTF-8 encoded English language explanation of the most recent +** error. +*/ +const char *sqlite3_errmsg(sqlite3 *db){ + const char *z; + if( !db ){ + return sqlite3ErrStr(SQLITE_NOMEM); + } + if( !sqlite3SafetyCheckSickOrOk(db) || db->errCode==SQLITE_MISUSE ){ + return sqlite3ErrStr(SQLITE_MISUSE); + } + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + z = (char*)sqlite3_value_text(db->pErr); + if( z==0 ){ + z = sqlite3ErrStr(db->errCode); + } + sqlite3_mutex_leave(db->mutex); + return z; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Return UTF-16 encoded English language explanation of the most recent +** error. +*/ +const void *sqlite3_errmsg16(sqlite3 *db){ + /* Because all the characters in the string are in the unicode + ** range 0x00-0xFF, if we pad the big-endian string with a + ** zero byte, we can obtain the little-endian string with + ** &big_endian[1]. + */ + static const char outOfMemBe[] = { + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 'm', 0, 'e', 0, 'm', 0, 'o', 0, 'r', 0, 'y', 0, 0, 0 + }; + static const char misuseBe [] = { + 0, 'l', 0, 'i', 0, 'b', 0, 'r', 0, 'a', 0, 'r', 0, 'y', 0, ' ', + 0, 'r', 0, 'o', 0, 'u', 0, 't', 0, 'i', 0, 'n', 0, 'e', 0, ' ', + 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 's', 0, 'e', 0, 'q', 0, 'u', 0, 'e', 0, 'n', 0, 'c', 0, 'e', 0, 0, 0 + }; + + const void *z; + if( !db ){ + return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); + } + if( !sqlite3SafetyCheckSickOrOk(db) || db->errCode==SQLITE_MISUSE ){ + return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); + } + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + z = sqlite3_value_text16(db->pErr); + if( z==0 ){ + sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), + SQLITE_UTF8, SQLITE_STATIC); + z = sqlite3_value_text16(db->pErr); + } + sqlite3ApiExit(0, 0); + sqlite3_mutex_leave(db->mutex); + return z; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Return the most recent error code generated by an SQLite routine. If NULL is +** passed to this function, we assume a malloc() failed during sqlite3_open(). +*/ +int sqlite3_errcode(sqlite3 *db){ + if( db && !sqlite3SafetyCheckSickOrOk(db) ){ + return SQLITE_MISUSE; + } + if( !db || db->mallocFailed ){ + return SQLITE_NOMEM; + } + return db->errCode & db->errMask; +} + +/* +** Create a new collating function for database "db". The name is zName +** and the encoding is enc. +*/ +static int createCollation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + CollSeq *pColl; + int enc2; + + assert( sqlite3_mutex_held(db->mutex) ); + + /* If SQLITE_UTF16 is specified as the encoding type, transform this + ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the + ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. + */ + enc2 = enc & ~SQLITE_UTF16_ALIGNED; + if( enc2==SQLITE_UTF16 ){ + enc2 = SQLITE_UTF16NATIVE; + } + + if( (enc2&~3)!=0 ){ + sqlite3Error(db, SQLITE_ERROR, "unknown encoding"); + return SQLITE_ERROR; + } + + /* Check if this call is removing or replacing an existing collation + ** sequence. If so, and there are active VMs, return busy. If there + ** are no active VMs, invalidate any pre-compiled statements. + */ + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0); + if( pColl && pColl->xCmp ){ + if( db->activeVdbeCnt ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to delete/modify collation sequence due to active statements"); + return SQLITE_BUSY; + } + sqlite3ExpirePreparedStatements(db); + + /* If collation sequence pColl was created directly by a call to + ** sqlite3_create_collation, and not generated by synthCollSeq(), + ** then any copies made by synthCollSeq() need to be invalidated. + ** Also, collation destructor - CollSeq.xDel() - function may need + ** to be called. + */ + if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, strlen(zName)); + int j; + for(j=0; j<3; j++){ + CollSeq *p = &aColl[j]; + if( p->enc==pColl->enc ){ + if( p->xDel ){ + p->xDel(p->pUser); + } + p->xCmp = 0; + } + } + } + } + + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); + if( pColl ){ + pColl->xCmp = xCompare; + pColl->pUser = pCtx; + pColl->xDel = xDel; + pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); + } + sqlite3Error(db, SQLITE_OK, 0); + return SQLITE_OK; +} + + +/* +** This routine does the work of opening a database on behalf of +** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" +** is UTF-8 encoded. +*/ +static int openDatabase( + const char *zFilename, /* Database filename UTF-8 encoded */ + sqlite3 **ppDb, /* OUT: Returned database handle */ + unsigned flags, /* Operational flags */ + const char *zVfs /* Name of the VFS to use */ +){ + sqlite3 *db; + int rc; + CollSeq *pColl; + + /* Allocate the sqlite data structure */ + db = sqlite3MallocZero( sizeof(sqlite3) ); + if( db==0 ) goto opendb_out; + db->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); + if( db->mutex==0 ){ + sqlite3_free(db); + db = 0; + goto opendb_out; + } + sqlite3_mutex_enter(db->mutex); + db->errMask = 0xff; + db->priorNewRowid = 0; + db->nDb = 2; + db->magic = SQLITE_MAGIC_BUSY; + db->aDb = db->aDbStatic; + db->autoCommit = 1; + db->nextAutovac = -1; + db->flags |= SQLITE_ShortColNames +#if SQLITE_DEFAULT_FILE_FORMAT<4 + | SQLITE_LegacyFileFmt +#endif +#ifdef SQLITE_ENABLE_LOAD_EXTENSION + | SQLITE_LoadExtension +#endif + ; + sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0); +#endif + + db->pVfs = sqlite3_vfs_find(zVfs); + if( !db->pVfs ){ + rc = SQLITE_ERROR; + db->magic = SQLITE_MAGIC_SICK; + sqlite3Error(db, rc, "no such vfs: %s", (zVfs?zVfs:"(null)")); + goto opendb_out; + } + + /* Add the default collation sequence BINARY. BINARY works for both UTF-8 + ** and UTF-16, so add a version for each to avoid any unnecessary + ** conversions. The only error that can occur here is a malloc() failure. + */ + if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0) || + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0) || + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0) || + createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0) || + (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 + ){ + assert( db->mallocFailed ); + db->magic = SQLITE_MAGIC_SICK; + goto opendb_out; + } + + /* Also add a UTF-8 case-insensitive collation sequence. */ + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); + + /* Set flags on the built-in collating sequences */ + db->pDfltColl->type = SQLITE_COLL_BINARY; + pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0); + if( pColl ){ + pColl->type = SQLITE_COLL_NOCASE; + } + + /* Open the backend database driver */ + db->openFlags = flags; + rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, + flags | SQLITE_OPEN_MAIN_DB, + &db->aDb[0].pBt); + if( rc!=SQLITE_OK ){ + sqlite3Error(db, rc, 0); + db->magic = SQLITE_MAGIC_SICK; + goto opendb_out; + } + db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); + db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); + + + /* The default safety_level for the main database is 'full'; for the temp + ** database it is 'NONE'. This matches the pager layer defaults. + */ + db->aDb[0].zName = "main"; + db->aDb[0].safety_level = 3; +#ifndef SQLITE_OMIT_TEMPDB + db->aDb[1].zName = "temp"; + db->aDb[1].safety_level = 1; +#endif + + db->magic = SQLITE_MAGIC_OPEN; + if( db->mallocFailed ){ + goto opendb_out; + } + + /* Register all built-in functions, but do not attempt to read the + ** database schema yet. This is delayed until the first time the database + ** is accessed. + */ + sqlite3Error(db, SQLITE_OK, 0); + sqlite3RegisterBuiltinFunctions(db); + + /* Load automatic extensions - extensions that have been registered + ** using the sqlite3_automatic_extension() API. + */ + (void)sqlite3AutoLoadExtensions(db); + if( sqlite3_errcode(db)!=SQLITE_OK ){ + goto opendb_out; + } + +#ifdef SQLITE_ENABLE_FTS1 + if( !db->mallocFailed ){ + extern int sqlite3Fts1Init(sqlite3*); + rc = sqlite3Fts1Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS2 + if( !db->mallocFailed && rc==SQLITE_OK ){ + extern int sqlite3Fts2Init(sqlite3*); + rc = sqlite3Fts2Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS3 + if( !db->mallocFailed && rc==SQLITE_OK ){ + rc = sqlite3Fts3Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_ICU + if( !db->mallocFailed && rc==SQLITE_OK ){ + extern int sqlite3IcuInit(sqlite3*); + rc = sqlite3IcuInit(db); + } +#endif + sqlite3Error(db, rc, 0); + + /* -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. + */ +#ifdef SQLITE_DEFAULT_LOCKING_MODE + db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; + sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), + SQLITE_DEFAULT_LOCKING_MODE); +#endif + +opendb_out: + if( db && db->mutex ){ + sqlite3_mutex_leave(db->mutex); + } + if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ + sqlite3_close(db); + db = 0; + } + *ppDb = db; + return sqlite3ApiExit(0, rc); +} + +/* +** Open a new database handle. +*/ +int sqlite3_open( + const char *zFilename, + sqlite3 **ppDb +){ + return openDatabase(zFilename, ppDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); +} +int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +){ + return openDatabase(filename, ppDb, flags, zVfs); +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Open a new database handle. +*/ +int sqlite3_open16( + const void *zFilename, + sqlite3 **ppDb +){ + char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ + sqlite3_value *pVal; + int rc = SQLITE_NOMEM; + + assert( zFilename ); + assert( ppDb ); + *ppDb = 0; + pVal = sqlite3ValueNew(0); + sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); + if( zFilename8 ){ + rc = openDatabase(zFilename8, ppDb, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); + if( rc==SQLITE_OK && *ppDb ){ + rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); + if( rc!=SQLITE_OK ){ + sqlite3_close(*ppDb); + *ppDb = 0; + } + } + } + sqlite3ValueFree(pVal); + + return sqlite3ApiExit(0, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + int rc; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + rc = createCollation(db, zName, enc, pCtx, xCompare, 0); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation_v2( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + int rc; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + rc = createCollation(db, zName, enc, pCtx, xCompare, xDel); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation16( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + int rc = SQLITE_OK; + char *zName8; + sqlite3_mutex_enter(db->mutex); + assert( !db->mallocFailed ); + zName8 = sqlite3Utf16to8(db, zName, -1); + if( zName8 ){ + rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); + sqlite3_free(zName8); + } + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Register a collation sequence factory callback with the database handle +** db. Replace any previously installed collation sequence factory. +*/ +int sqlite3_collation_needed( + sqlite3 *db, + void *pCollNeededArg, + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) +){ + sqlite3_mutex_enter(db->mutex); + db->xCollNeeded = xCollNeeded; + db->xCollNeeded16 = 0; + db->pCollNeededArg = pCollNeededArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Register a collation sequence factory callback with the database handle +** db. Replace any previously installed collation sequence factory. +*/ +int sqlite3_collation_needed16( + sqlite3 *db, + void *pCollNeededArg, + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) +){ + sqlite3_mutex_enter(db->mutex); + db->xCollNeeded = 0; + db->xCollNeeded16 = xCollNeeded16; + db->pCollNeededArg = pCollNeededArg; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} +#endif /* SQLITE_OMIT_UTF16 */ + +#ifndef SQLITE_OMIT_GLOBALRECOVER +/* +** This function is now an anachronism. It used to be used to recover from a +** malloc() failure, but SQLite now does this automatically. +*/ +int sqlite3_global_recover(void){ + return SQLITE_OK; +} +#endif + +/* +** Test to see whether or not the database connection is in autocommit +** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on +** by default. Autocommit is disabled by a BEGIN statement and reenabled +** by the next COMMIT or ROLLBACK. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +int sqlite3_get_autocommit(sqlite3 *db){ + return db->autoCommit; +} + +#ifdef SQLITE_DEBUG +/* +** The following routine is subtituted for constant SQLITE_CORRUPT in +** debugging builds. This provides a way to set a breakpoint for when +** corruption is first detected. +*/ +int sqlite3Corrupt(void){ + return SQLITE_CORRUPT; +} +#endif + +/* +** This is a convenience routine that makes sure that all thread-specific +** data for this thread has been deallocated. +** +** SQLite no longer uses thread-specific data so this routine is now a +** no-op. It is retained for historical compatibility. +*/ +void sqlite3_thread_cleanup(void){ +} + +/* +** Return meta information about a specific column of a database table. +** See comment in sqlite3.h (sqlite.h.in) for details. +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if colums is auto-increment */ +){ + int rc; + char *zErrMsg = 0; + Table *pTab = 0; + Column *pCol = 0; + int iCol; + + char const *zDataType = 0; + char const *zCollSeq = 0; + int notnull = 0; + int primarykey = 0; + int autoinc = 0; + + /* Ensure the database schema has been loaded */ + (void)sqlite3SafetyOn(db); + sqlite3_mutex_enter(db->mutex); + rc = sqlite3Init(db, &zErrMsg); + if( SQLITE_OK!=rc ){ + goto error_out; + } + + /* Locate the table in question */ + pTab = sqlite3FindTable(db, zTableName, zDbName); + if( !pTab || pTab->pSelect ){ + pTab = 0; + goto error_out; + } + + /* Find the column for which info is requested */ + if( sqlite3IsRowid(zColumnName) ){ + iCol = pTab->iPKey; + if( iCol>=0 ){ + pCol = &pTab->aCol[iCol]; + } + }else{ + for(iCol=0; iColnCol; iCol++){ + pCol = &pTab->aCol[iCol]; + if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ + break; + } + } + if( iCol==pTab->nCol ){ + pTab = 0; + goto error_out; + } + } + + /* The following block stores the meta information that will be returned + ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey + ** and autoinc. At this point there are two possibilities: + ** + ** 1. The specified column name was rowid", "oid" or "_rowid_" + ** and there is no explicitly declared IPK column. + ** + ** 2. The table is not a view and the column name identified an + ** explicitly declared column. Copy meta information from *pCol. + */ + if( pCol ){ + zDataType = pCol->zType; + zCollSeq = pCol->zColl; + notnull = (pCol->notNull?1:0); + primarykey = (pCol->isPrimKey?1:0); + autoinc = ((pTab->iPKey==iCol && pTab->autoInc)?1:0); + }else{ + zDataType = "INTEGER"; + primarykey = 1; + } + if( !zCollSeq ){ + zCollSeq = "BINARY"; + } + +error_out: + (void)sqlite3SafetyOff(db); + + /* Whether the function call succeeded or failed, set the output parameters + ** to whatever their local counterparts contain. If an error did occur, + ** this has the effect of zeroing all output parameters. + */ + if( pzDataType ) *pzDataType = zDataType; + if( pzCollSeq ) *pzCollSeq = zCollSeq; + if( pNotNull ) *pNotNull = notnull; + if( pPrimaryKey ) *pPrimaryKey = primarykey; + if( pAutoinc ) *pAutoinc = autoinc; + + if( SQLITE_OK==rc && !pTab ){ + sqlite3SetString(&zErrMsg, "no such table column: ", zTableName, ".", + zColumnName, 0); + rc = SQLITE_ERROR; + } + sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqlite3_free(zErrMsg); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} +#endif + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +int sqlite3_sleep(int ms){ + sqlite3_vfs *pVfs; + int rc; + pVfs = sqlite3_vfs_find(0); + + /* This function works in milliseconds, but the underlying OsSleep() + ** API uses microseconds. Hence the 1000's. + */ + rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); + return rc; +} + +/* +** Enable or disable the extended result codes. +*/ +int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ + sqlite3_mutex_enter(db->mutex); + db->errMask = onoff ? 0xffffffff : 0xff; + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + +/* +** Invoke the xFileControl method on a particular database. +*/ +int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ + int rc = SQLITE_ERROR; + int iDb; + sqlite3_mutex_enter(db->mutex); + if( zDbName==0 ){ + iDb = 0; + }else{ + for(iDb=0; iDbnDb; iDb++){ + if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break; + } + } + if( iDbnDb ){ + Btree *pBtree = db->aDb[iDb].pBt; + if( pBtree ){ + Pager *pPager; + sqlite3_file *fd; + sqlite3BtreeEnter(pBtree); + pPager = sqlite3BtreePager(pBtree); + assert( pPager!=0 ); + fd = sqlite3PagerFile(pPager); + assert( fd!=0 ); + if( fd->pMethods ){ + rc = sqlite3OsFileControl(fd, op, pArg); + } + sqlite3BtreeLeave(pBtree); + } + } + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Interface to the testing logic. +*/ +int sqlite3_test_control(int op, ...){ + va_list ap; + int rc = 0; + va_start(ap, op); + switch( op ){ +#ifndef SQLITE_OMIT_FAULTINJECTOR + case SQLITE_TESTCTRL_FAULT_CONFIG: { + int id = va_arg(ap, int); + int nDelay = va_arg(ap, int); + int nRepeat = va_arg(ap, int); + sqlite3FaultConfig(id, nDelay, nRepeat); + break; + } + case SQLITE_TESTCTRL_FAULT_FAILURES: { + int id = va_arg(ap, int); + rc = sqlite3FaultFailures(id); + break; + } + case SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES: { + int id = va_arg(ap, int); + rc = sqlite3FaultBenignFailures(id); + break; + } + case SQLITE_TESTCTRL_FAULT_PENDING: { + int id = va_arg(ap, int); + rc = sqlite3FaultPending(id); + break; + } +#endif /* SQLITE_OMIT_FAULTINJECTOR */ + } + va_end(ap); + return rc; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/malloc.c b/client/src/thirdparty/sqlite-3.4.2/src/malloc.c new file mode 100644 index 0000000..a047348 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/malloc.c @@ -0,0 +1,239 @@ +/* +** 2001 September 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. +** +************************************************************************* +** Memory allocation functions used throughout sqlite. +** +** +** $Id: malloc.c,v 1.14 2007/10/20 16:36:31 drh Exp $ +*/ +#include "sqliteInt.h" +#include +#include + +/* +** This routine runs when the memory allocator sees that the +** total memory allocation is about to exceed the soft heap +** limit. +*/ +static void softHeapLimitEnforcer( + void *NotUsed, + sqlite3_int64 inUse, + int allocSize +){ + sqlite3_release_memory(allocSize); +} + +/* +** Set the soft heap-size limit for the current thread. Passing a +** zero or negative value indicates no limit. +*/ +void sqlite3_soft_heap_limit(int n){ + sqlite3_uint64 iLimit; + int overage; + if( n<0 ){ + iLimit = 0; + }else{ + iLimit = n; + } + if( iLimit>0 ){ + sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit); + }else{ + sqlite3_memory_alarm(0, 0, 0); + } + overage = sqlite3_memory_used() - n; + if( overage>0 ){ + sqlite3_release_memory(overage); + } +} + +/* +** Release memory held by SQLite instances created by the current thread. +*/ +int sqlite3_release_memory(int n){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + return sqlite3PagerReleaseMemory(n); +#else + return SQLITE_OK; +#endif +} + + +/* +** Allocate and zero memory. +*/ +void *sqlite3MallocZero(unsigned n){ + void *p = sqlite3_malloc(n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* +** Allocate and zero memory. If the allocation fails, make +** the mallocFailed flag in the connection pointer. +*/ +void *sqlite3DbMallocZero(sqlite3 *db, unsigned n){ + void *p = sqlite3DbMallocRaw(db, n); + if( p ){ + memset(p, 0, n); + } + return p; +} + +/* +** Allocate and zero memory. If the allocation fails, make +** the mallocFailed flag in the connection pointer. +*/ +void *sqlite3DbMallocRaw(sqlite3 *db, unsigned n){ + void *p = 0; + if( !db || db->mallocFailed==0 ){ + p = sqlite3_malloc(n); + if( !p && db ){ + db->mallocFailed = 1; + } + } + return p; +} + +/* +** Resize the block of memory pointed to by p to n bytes. If the +** resize fails, set the mallocFailed flag inthe connection object. +*/ +void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){ + void *pNew = 0; + if( db->mallocFailed==0 ){ + pNew = sqlite3_realloc(p, n); + if( !pNew ){ + db->mallocFailed = 1; + } + } + return pNew; +} + +/* +** Attempt to reallocate p. If the reallocation fails, then free p +** and set the mallocFailed flag in the database connection. +*/ +void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){ + void *pNew; + pNew = sqlite3DbRealloc(db, p, n); + if( !pNew ){ + sqlite3_free(p); + } + return pNew; +} + +/* +** Make a copy of a string in memory obtained from sqliteMalloc(). These +** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This +** is because when memory debugging is turned on, these two functions are +** called via macros that record the current file and line number in the +** ThreadData structure. +*/ +char *sqlite3StrDup(const char *z){ + char *zNew; + int n; + if( z==0 ) return 0; + n = strlen(z)+1; + zNew = sqlite3_malloc(n); + if( zNew ) memcpy(zNew, z, n); + return zNew; +} +char *sqlite3StrNDup(const char *z, int n){ + char *zNew; + if( z==0 ) return 0; + zNew = sqlite3_malloc(n+1); + if( zNew ){ + memcpy(zNew, z, n); + zNew[n] = 0; + } + return zNew; +} + +char *sqlite3DbStrDup(sqlite3 *db, const char *z){ + char *zNew = sqlite3StrDup(z); + if( z && !zNew ){ + db->mallocFailed = 1; + } + return zNew; +} +char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){ + char *zNew = sqlite3StrNDup(z, n); + if( z && !zNew ){ + db->mallocFailed = 1; + } + return zNew; +} + +/* +** Create a string from the 2nd and subsequent arguments (up to the +** first NULL argument), store the string in memory obtained from +** sqliteMalloc() and make the pointer indicated by the 1st argument +** point to that string. The 1st argument must either be NULL or +** point to memory obtained from sqliteMalloc(). +*/ +void sqlite3SetString(char **pz, ...){ + va_list ap; + int nByte; + const char *z; + char *zResult; + + assert( pz!=0 ); + nByte = 1; + va_start(ap, pz); + while( (z = va_arg(ap, const char*))!=0 ){ + nByte += strlen(z); + } + va_end(ap); + sqlite3_free(*pz); + *pz = zResult = sqlite3_malloc(nByte); + if( zResult==0 ){ + return; + } + *zResult = 0; + va_start(ap, pz); + while( (z = va_arg(ap, const char*))!=0 ){ + int n = strlen(z); + memcpy(zResult, z, n); + zResult += n; + } + zResult[0] = 0; + va_end(ap); +} + + +/* +** This function must be called before exiting any API function (i.e. +** returning control to the user) that has called sqlite3_malloc or +** sqlite3_realloc. +** +** The returned value is normally a copy of the second argument to this +** function. However, if a malloc() failure has occured since the previous +** invocation SQLITE_NOMEM is returned instead. +** +** If the first argument, db, is not NULL and a malloc() error has occured, +** then the connection error-code (the value returned by sqlite3_errcode()) +** is set to SQLITE_NOMEM. +*/ +int sqlite3ApiExit(sqlite3* db, int rc){ + /* If the db handle is not NULL, then we must hold the connection handle + ** mutex here. Otherwise the read (and possible write) of db->mallocFailed + ** is unsafe, as is the call to sqlite3Error(). + */ + assert( !db || sqlite3_mutex_held(db->mutex) ); + if( db && db->mallocFailed ){ + sqlite3Error(db, SQLITE_NOMEM, 0); + db->mallocFailed = 0; + rc = SQLITE_NOMEM; + } + return rc & (db ? db->errMask : 0xff); +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/md5.c b/client/src/thirdparty/sqlite-3.4.2/src/md5.c new file mode 100644 index 0000000..a4c9931 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/md5.c @@ -0,0 +1,387 @@ +/* +** SQLite uses this code for testing only. It is not a part of +** the SQLite library. This file implements two new TCL commands +** "md5" and "md5file" that compute md5 checksums on arbitrary text +** and on complete files. These commands are used by the "testfixture" +** program to help verify the correct operation of the SQLite library. +** +** The original use of these TCL commands was to test the ROLLBACK +** feature of SQLite. First compute the MD5-checksum of the database. +** Then make some changes but rollback the changes rather than commit +** them. Compute a second MD5-checksum of the file and verify that the +** two checksums are the same. Such is the original use of this code. +** New uses may have been added since this comment was written. +*/ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +#include +#include +#include "sqlite3.h" + +/* + * If compiled on a machine that doesn't have a 32-bit integer, + * you just set "uint32" to the appropriate datatype for an + * unsigned 32-bit integer. For example: + * + * cc -Duint32='unsigned long' md5.c + * + */ +#ifndef uint32 +# define uint32 unsigned int +#endif + +struct Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; +typedef char MD5Context[88]; + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse (unsigned char *buf, unsigned longs){ + uint32 t; + do { + t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | + ((unsigned)buf[1]<<8 | buf[0]); + *(uint32 *)buf = t; + buf += 4; + } while (--longs); +} +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(uint32 buf[4], const uint32 in[16]){ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +static void MD5Init(MD5Context *pCtx){ + struct Context *ctx = (struct Context *)pCtx; + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +static +void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){ + struct Context *ctx = (struct Context *)pCtx; + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32)len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if ( t ) { + unsigned char *p = (unsigned char *)ctx->in + t; + + t = 64-t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +static void MD5Final(unsigned char digest[16], MD5Context *pCtx){ + struct Context *ctx = (struct Context *)pCtx; + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *)ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count-8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0]; + ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *)ctx->in); + byteReverse((unsigned char *)ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* +** Convert a digest into base-16. digest should be declared as +** "unsigned char digest[16]" in the calling function. The MD5 +** digest is stored in the first 16 bytes. zBuf should +** be "char zBuf[33]". +*/ +static void DigestToBase16(unsigned char *digest, char *zBuf){ + static char const zEncode[] = "0123456789abcdef"; + int i, j; + + for(j=i=0; i<16; i++){ + int a = digest[i]; + zBuf[j++] = zEncode[(a>>4)&0xf]; + zBuf[j++] = zEncode[a & 0xf]; + } + zBuf[j] = 0; +} + +/* +** A TCL command for md5. The argument is the text to be hashed. The +** Result is the hash in base64. +*/ +static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){ + MD5Context ctx; + unsigned char digest[16]; + + if( argc!=2 ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " TEXT\"", 0); + return TCL_ERROR; + } + MD5Init(&ctx); + MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1])); + MD5Final(digest, &ctx); + DigestToBase16(digest, interp->result); + return TCL_OK; +} + +/* +** A TCL command to take the md5 hash of a file. The argument is the +** name of the file. +*/ +static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){ + FILE *in; + MD5Context ctx; + unsigned char digest[16]; + char zBuf[10240]; + + if( argc!=2 ){ + Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], + " FILENAME\"", 0); + return TCL_ERROR; + } + in = fopen(argv[1],"rb"); + if( in==0 ){ + Tcl_AppendResult(interp,"unable to open file \"", argv[1], + "\" for reading", 0); + return TCL_ERROR; + } + MD5Init(&ctx); + for(;;){ + int n; + n = fread(zBuf, 1, sizeof(zBuf), in); + if( n<=0 ) break; + MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); + } + fclose(in); + MD5Final(digest, &ctx); + DigestToBase16(digest, interp->result); + return TCL_OK; +} + +/* +** Register the two TCL commands above with the TCL interpreter. +*/ +int Md5_Init(Tcl_Interp *interp){ + Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0); + Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0); + return TCL_OK; +} + +/* +** During testing, the special md5sum() aggregate function is available. +** inside SQLite. The following routines implement that function. +*/ +static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){ + MD5Context *p; + int i; + if( argc<1 ) return; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( p==0 ) return; + if( sqlite3_aggregate_count(context)==1 ){ + MD5Init(p); + } + for(i=0; i0 ){ + enterMem(); + if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes); + } + p = malloc(nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = malloc(nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + sqlite3_mutex_leave(mem.mutex); + } + return (void*)p; +} + +/* +** Free memory. +*/ +void sqlite3_free(void *pPrior){ + sqlite3_int64 *p; + int nByte; + if( pPrior==0 ){ + return; + } + assert( mem.mutex!=0 ); + p = pPrior; + p--; + nByte = (int)*p; + sqlite3_mutex_enter(mem.mutex); + mem.nowUsed -= nByte; + free(p); + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Change the size of an existing memory allocation +*/ +void *sqlite3_realloc(void *pPrior, int nBytes){ + int nOld; + sqlite3_int64 *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + p = pPrior; + p--; + nOld = (int)p[0]; + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + if( mem.nowUsed+nBytes-nOld>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes-nOld); + } + p = realloc(p, nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = pPrior; + p--; + p = realloc(p, nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes-nOld; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + sqlite3_mutex_leave(mem.mutex); + return (void*)p; +} + +#endif /* !SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mem2.c b/client/src/thirdparty/sqlite-3.4.2/src/mem2.c new file mode 100644 index 0000000..0c99c63 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mem2.c @@ -0,0 +1,456 @@ +/* +** 2007 August 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. +** +************************************************************************* +** This file contains the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** $Id: mem2.c,v 1.19 2008/01/22 21:30:53 drh Exp $ +*/ + +/* +** This version of the memory allocator is used only if the +** SQLITE_MEMDEBUG macro is defined and SQLITE_OMIT_MEMORY_ALLOCATION +** is not defined. +*/ +#if defined(SQLITE_MEMDEBUG) + +/* +** We will eventually construct multiple memory allocation subsystems +** suitable for use in various contexts: +** +** * Normal multi-threaded builds +** * Normal single-threaded builds +** * Debugging builds +** +** This version is suitable for use in debugging builds. +** +** Features: +** +** * Every allocate has guards at both ends. +** * New allocations are initialized with randomness +** * Allocations are overwritten with randomness when freed +** * Optional logs of malloc activity generated +** * Summary of outstanding allocations with backtraces to the +** point of allocation. +** * The ability to simulate memory allocation failure +*/ +#include "sqliteInt.h" +#include + +/* +** The backtrace functionality is only available with GLIBC +*/ +#ifdef __GLIBC__ + extern int backtrace(void**,int); + extern void backtrace_symbols_fd(void*const*,int,int); +#else +# define backtrace(A,B) 0 +# define backtrace_symbols_fd(A,B,C) +#endif + +/* +** Each memory allocation looks like this: +** +** ------------------------------------------------------------------------ +** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard | +** ------------------------------------------------------------------------ +** +** The application code sees only a pointer to the allocation. We have +** to back up from the allocation pointer to find the MemBlockHdr. The +** MemBlockHdr tells us the size of the allocation and the number of +** backtrace pointers. There is also a guard word at the end of the +** MemBlockHdr. +*/ +struct MemBlockHdr { + struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */ + int iSize; /* Size of this allocation */ + char nBacktrace; /* Number of backtraces on this alloc */ + char nBacktraceSlots; /* Available backtrace slots */ + short nTitle; /* Bytes of title; includes '\0' */ + int iForeGuard; /* Guard word for sanity */ +}; + +/* +** Guard words +*/ +#define FOREGUARD 0x80F5E153 +#define REARGUARD 0xE4676B53 + +/* +** Number of malloc size increments to track. +*/ +#define NCSIZE 1000 + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** The alarm callback and its arguments. The mem.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. The alarmBusy variable is set to prevent recursive + ** callbacks. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64, int); + void *alarmArg; + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Current allocation and high-water mark. + */ + sqlite3_int64 nowUsed; + sqlite3_int64 mxUsed; + + /* + ** Head and tail of a linked list of all outstanding allocations + */ + struct MemBlockHdr *pFirst; + struct MemBlockHdr *pLast; + + /* + ** The number of levels of backtrace to save in new allocations. + */ + int nBacktrace; + + /* + ** Title text to insert in front of each block + */ + int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */ + char zTitle[100]; /* The title text */ + + /* + ** sqlite3MallocDisallow() increments the following counter. + ** sqlite3MallocAllow() decrements it. + */ + int disallow; /* Do not allow memory allocation */ + + /* + ** Gather statistics on the sizes of memory allocations. + ** sizeCnt[i] is the number of allocation attempts of i*8 + ** bytes. i==NCSIZE is the number of allocation attempts for + ** sizes more than NCSIZE*8 bytes. + */ + int sizeCnt[NCSIZE]; + +} mem; + + +/* +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. +*/ +static void enterMem(void){ + if( mem.mutex==0 ){ + mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem.mutex); +} + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + enterMem(); + n = mem.nowUsed; + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; + enterMem(); + n = mem.mxUsed; + if( resetFlag ){ + mem.mxUsed = mem.nowUsed; + } + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Change the alarm callback +*/ +int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used, int N), + void *pArg, + sqlite3_int64 iThreshold +){ + enterMem(); + mem.alarmCallback = xCallback; + mem.alarmArg = pArg; + mem.alarmThreshold = iThreshold; + sqlite3_mutex_leave(mem.mutex); + return SQLITE_OK; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MemsysAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem.alarmCallback==0 || mem.alarmBusy ) return; + mem.alarmBusy = 1; + xCallback = mem.alarmCallback; + nowUsed = mem.nowUsed; + pArg = mem.alarmArg; + sqlite3_mutex_leave(mem.mutex); + xCallback(pArg, nowUsed, nByte); + sqlite3_mutex_enter(mem.mutex); + mem.alarmBusy = 0; +} + +/* +** Given an allocation, find the MemBlockHdr for that allocation. +** +** This routine checks the guards at either end of the allocation and +** if they are incorrect it asserts. +*/ +static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){ + struct MemBlockHdr *p; + int *pInt; + + p = (struct MemBlockHdr*)pAllocation; + p--; + assert( p->iForeGuard==FOREGUARD ); + assert( (p->iSize & 3)==0 ); + pInt = (int*)pAllocation; + assert( pInt[p->iSize/sizeof(int)]==REARGUARD ); + return p; +} + +/* +** Allocate nByte bytes of memory. +*/ +void *sqlite3_malloc(int nByte){ + struct MemBlockHdr *pHdr; + void **pBt; + char *z; + int *pInt; + void *p = 0; + int totalSize; + + if( nByte>0 ){ + enterMem(); + assert( mem.disallow==0 ); + if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nByte); + } + nByte = (nByte+3)&~3; + if( nByte/8>NCSIZE-1 ){ + mem.sizeCnt[NCSIZE-1]++; + }else{ + mem.sizeCnt[nByte/8]++; + } + totalSize = nByte + sizeof(*pHdr) + sizeof(int) + + mem.nBacktrace*sizeof(void*) + mem.nTitle; + if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){ + p = 0; + }else{ + p = malloc(totalSize); + if( p==0 ){ + sqlite3MemsysAlarm(nByte); + p = malloc(totalSize); + } + } + if( p ){ + z = p; + pBt = (void**)&z[mem.nTitle]; + pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; + pHdr->pNext = 0; + pHdr->pPrev = mem.pLast; + if( mem.pLast ){ + mem.pLast->pNext = pHdr; + }else{ + mem.pFirst = pHdr; + } + mem.pLast = pHdr; + pHdr->iForeGuard = FOREGUARD; + pHdr->nBacktraceSlots = mem.nBacktrace; + pHdr->nTitle = mem.nTitle; + if( mem.nBacktrace ){ + void *aAddr[40]; + pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; + memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); + }else{ + pHdr->nBacktrace = 0; + } + if( mem.nTitle ){ + memcpy(z, mem.zTitle, mem.nTitle); + } + pHdr->iSize = nByte; + pInt = (int*)&pHdr[1]; + pInt[nByte/sizeof(int)] = REARGUARD; + memset(pInt, 0x65, nByte); + mem.nowUsed += nByte; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + p = (void*)pInt; + } + sqlite3_mutex_leave(mem.mutex); + } + return p; +} + +/* +** Free memory. +*/ +void sqlite3_free(void *pPrior){ + struct MemBlockHdr *pHdr; + void **pBt; + char *z; + if( pPrior==0 ){ + return; + } + assert( mem.mutex!=0 ); + pHdr = sqlite3MemsysGetHeader(pPrior); + pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + sqlite3_mutex_enter(mem.mutex); + mem.nowUsed -= pHdr->iSize; + if( pHdr->pPrev ){ + assert( pHdr->pPrev->pNext==pHdr ); + pHdr->pPrev->pNext = pHdr->pNext; + }else{ + assert( mem.pFirst==pHdr ); + mem.pFirst = pHdr->pNext; + } + if( pHdr->pNext ){ + assert( pHdr->pNext->pPrev==pHdr ); + pHdr->pNext->pPrev = pHdr->pPrev; + }else{ + assert( mem.pLast==pHdr ); + mem.pLast = pHdr->pPrev; + } + z = (char*)pBt; + z -= pHdr->nTitle; + memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) + + pHdr->iSize + sizeof(int) + pHdr->nTitle); + free(z); + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Change the size of an existing memory allocation. +** +** For this debugging implementation, we *always* make a copy of the +** allocation into a new place in memory. In this way, if the +** higher level code is using pointer to the old allocation, it is +** much more likely to break and we are much more liking to find +** the error. +*/ +void *sqlite3_realloc(void *pPrior, int nByte){ + struct MemBlockHdr *pOldHdr; + void *pNew; + if( pPrior==0 ){ + return sqlite3_malloc(nByte); + } + if( nByte<=0 ){ + sqlite3_free(pPrior); + return 0; + } + assert( mem.disallow==0 ); + pOldHdr = sqlite3MemsysGetHeader(pPrior); + pNew = sqlite3_malloc(nByte); + if( pNew ){ + memcpy(pNew, pPrior, nByteiSize ? nByte : pOldHdr->iSize); + if( nByte>pOldHdr->iSize ){ + memset(&((char*)pNew)[pOldHdr->iSize], 0x2b, nByte - pOldHdr->iSize); + } + sqlite3_free(pPrior); + } + return pNew; +} + +/* +** Set the number of backtrace levels kept for each allocation. +** A value of zero turns of backtracing. The number is always rounded +** up to a multiple of 2. +*/ +void sqlite3_memdebug_backtrace(int depth){ + if( depth<0 ){ depth = 0; } + if( depth>20 ){ depth = 20; } + depth = (depth+1)&0xfe; + mem.nBacktrace = depth; +} + +/* +** Set the title string for subsequent allocations. +*/ +void sqlite3_memdebug_settitle(const char *zTitle){ + int n = strlen(zTitle) + 1; + enterMem(); + if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; + memcpy(mem.zTitle, zTitle, n); + mem.zTitle[n] = 0; + mem.nTitle = (n+3)&~3; + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Open the file indicated and write a log of all unfreed memory +** allocations into that log. +*/ +void sqlite3_memdebug_dump(const char *zFilename){ + FILE *out; + struct MemBlockHdr *pHdr; + void **pBt; + int i; + out = fopen(zFilename, "w"); + if( out==0 ){ + fprintf(stderr, "** Unable to output memory debug output log: %s **\n", + zFilename); + return; + } + for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){ + char *z = (char*)pHdr; + z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle; + fprintf(out, "**** %d bytes at %p from %s ****\n", + pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???"); + if( pHdr->nBacktrace ){ + fflush(out); + pBt = (void**)pHdr; + pBt -= pHdr->nBacktraceSlots; + backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out)); + fprintf(out, "\n"); + } + } + fprintf(out, "COUNTS:\n"); + for(i=0; i%3d: %d\n", NCSIZE*8, mem.sizeCnt[NCSIZE-1]); + } + fclose(out); +} + + +#endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mem3.c b/client/src/thirdparty/sqlite-3.4.2/src/mem3.c new file mode 100644 index 0000000..0d98372 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mem3.c @@ -0,0 +1,653 @@ +/* +** 2007 October 14 +** +** 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 the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** This version of the memory allocation subsystem omits all +** use of malloc(). All dynamically allocatable memory is +** contained in a static array, mem.aPool[]. The size of this +** fixed memory pool is SQLITE_MEMORY_SIZE bytes. +** +** This version of the memory allocation subsystem is used if +** and only if SQLITE_MEMORY_SIZE is defined. +** +** $Id: mem3.c,v 1.8 2007/12/29 13:18:22 drh Exp $ +*/ + +/* +** This version of the memory allocator is used only when +** SQLITE_MEMORY_SIZE is defined. +*/ +#if defined(SQLITE_MEMORY_SIZE) +#include "sqliteInt.h" + +#ifdef SQLITE_MEMDEBUG +# error cannot define both SQLITE_MEMDEBUG and SQLITE_MEMORY_SIZE +#endif + +/* +** Maximum size (in Mem3Blocks) of a "small" chunk. +*/ +#define MX_SMALL 10 + + +/* +** Number of freelist hash slots +*/ +#define N_HASH 61 + +/* +** A memory allocation (also called a "chunk") consists of two or +** more blocks where each block is 8 bytes. The first 8 bytes are +** a header that is not returned to the user. +** +** A chunk is two or more blocks that is either checked out or +** free. The first block has format u.hdr. u.hdr.size4x is 4 times the +** size of the allocation in blocks if the allocation is free. +** The u.hdr.size4x&1 bit is true if the chunk is checked out and +** false if the chunk is on the freelist. The u.hdr.size4x&2 bit +** is true if the previous chunk is checked out and false if the +** previous chunk is free. The u.hdr.prevSize field is the size of +** the previous chunk in blocks if the previous chunk is on the +** freelist. If the previous chunk is checked out, then +** u.hdr.prevSize can be part of the data for that chunk and should +** not be read or written. +** +** We often identify a chunk by its index in mem.aPool[]. When +** this is done, the chunk index refers to the second block of +** the chunk. In this way, the first chunk has an index of 1. +** A chunk index of 0 means "no such chunk" and is the equivalent +** of a NULL pointer. +** +** The second block of free chunks is of the form u.list. The +** two fields form a double-linked list of chunks of related sizes. +** Pointers to the head of the list are stored in mem.aiSmall[] +** for smaller chunks and mem.aiHash[] for larger chunks. +** +** The second block of a chunk is user data if the chunk is checked +** out. If a chunk is checked out, the user data may extend into +** the u.hdr.prevSize value of the following chunk. +*/ +typedef struct Mem3Block Mem3Block; +struct Mem3Block { + union { + struct { + u32 prevSize; /* Size of previous chunk in Mem3Block elements */ + u32 size4x; /* 4x the size of current chunk in Mem3Block elements */ + } hdr; + struct { + u32 next; /* Index in mem.aPool[] of next free chunk */ + u32 prev; /* Index in mem.aPool[] of previous free chunk */ + } list; + } u; +}; + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** True if we are evaluating an out-of-memory callback. + */ + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** The minimum amount of free space that we have seen. + */ + u32 mnMaster; + + /* + ** iMaster is the index of the master chunk. Most new allocations + ** occur off of this chunk. szMaster is the size (in Mem3Blocks) + ** of the current master. iMaster is 0 if there is not master chunk. + ** The master chunk is not in either the aiHash[] or aiSmall[]. + */ + u32 iMaster; + u32 szMaster; + + /* + ** Array of lists of free blocks according to the block size + ** for smaller chunks, or a hash on the block size for larger + ** chunks. + */ + u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */ + u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */ + + /* + ** Memory available for allocation + */ + Mem3Block aPool[SQLITE_MEMORY_SIZE/sizeof(Mem3Block)+2]; +} mem; + +/* +** Unlink the chunk at mem.aPool[i] from list it is currently +** on. *pRoot is the list that i is a member of. +*/ +static void memsys3UnlinkFromList(u32 i, u32 *pRoot){ + u32 next = mem.aPool[i].u.list.next; + u32 prev = mem.aPool[i].u.list.prev; + assert( sqlite3_mutex_held(mem.mutex) ); + if( prev==0 ){ + *pRoot = next; + }else{ + mem.aPool[prev].u.list.next = next; + } + if( next ){ + mem.aPool[next].u.list.prev = prev; + } + mem.aPool[i].u.list.next = 0; + mem.aPool[i].u.list.prev = 0; +} + +/* +** Unlink the chunk at index i from +** whatever list is currently a member of. +*/ +static void memsys3Unlink(u32 i){ + u32 size, hash; + assert( sqlite3_mutex_held(mem.mutex) ); + assert( (mem.aPool[i-1].u.hdr.size4x & 1)==0 ); + assert( i>=1 ); + size = mem.aPool[i-1].u.hdr.size4x/4; + assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); + assert( size>=2 ); + if( size <= MX_SMALL ){ + memsys3UnlinkFromList(i, &mem.aiSmall[size-2]); + }else{ + hash = size % N_HASH; + memsys3UnlinkFromList(i, &mem.aiHash[hash]); + } +} + +/* +** Link the chunk at mem.aPool[i] so that is on the list rooted +** at *pRoot. +*/ +static void memsys3LinkIntoList(u32 i, u32 *pRoot){ + assert( sqlite3_mutex_held(mem.mutex) ); + mem.aPool[i].u.list.next = *pRoot; + mem.aPool[i].u.list.prev = 0; + if( *pRoot ){ + mem.aPool[*pRoot].u.list.prev = i; + } + *pRoot = i; +} + +/* +** Link the chunk at index i into either the appropriate +** small chunk list, or into the large chunk hash table. +*/ +static void memsys3Link(u32 i){ + u32 size, hash; + assert( sqlite3_mutex_held(mem.mutex) ); + assert( i>=1 ); + assert( (mem.aPool[i-1].u.hdr.size4x & 1)==0 ); + size = mem.aPool[i-1].u.hdr.size4x/4; + assert( size==mem.aPool[i+size-1].u.hdr.prevSize ); + assert( size>=2 ); + if( size <= MX_SMALL ){ + memsys3LinkIntoList(i, &mem.aiSmall[size-2]); + }else{ + hash = size % N_HASH; + memsys3LinkIntoList(i, &mem.aiHash[hash]); + } +} + +/* +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. +** +** Also: Initialize the memory allocation subsystem the first time +** this routine is called. +*/ +static void memsys3Enter(void){ + if( mem.mutex==0 ){ + mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + mem.aPool[0].u.hdr.size4x = SQLITE_MEMORY_SIZE/2 + 2; + mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.prevSize = SQLITE_MEMORY_SIZE/8; + mem.aPool[SQLITE_MEMORY_SIZE/8].u.hdr.size4x = 1; + mem.iMaster = 1; + mem.szMaster = SQLITE_MEMORY_SIZE/8; + mem.mnMaster = mem.szMaster; + } + sqlite3_mutex_enter(mem.mutex); +} + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + memsys3Enter(); + n = SQLITE_MEMORY_SIZE - mem.szMaster*8; + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; + memsys3Enter(); + n = SQLITE_MEMORY_SIZE - mem.mnMaster*8; + if( resetFlag ){ + mem.mnMaster = mem.szMaster; + } + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Change the alarm callback. +** +** This is a no-op for the static memory allocator. The purpose +** of the memory alarm is to support sqlite3_soft_heap_limit(). +** But with this memory allocator, the soft_heap_limit is really +** a hard limit that is fixed at SQLITE_MEMORY_SIZE. +*/ +int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + return SQLITE_OK; +} + +/* +** Called when we are unable to satisfy an allocation of nBytes. +*/ +static void memsys3OutOfMemory(int nByte){ + if( !mem.alarmBusy ){ + mem.alarmBusy = 1; + assert( sqlite3_mutex_held(mem.mutex) ); + sqlite3_mutex_leave(mem.mutex); + sqlite3_release_memory(nByte); + sqlite3_mutex_enter(mem.mutex); + mem.alarmBusy = 0; + } +} + +/* +** Return the size of an outstanding allocation, in bytes. The +** size returned omits the 8-byte header overhead. This only +** works for chunks that are currently checked out. +*/ +static int memsys3Size(void *p){ + Mem3Block *pBlock = (Mem3Block*)p; + assert( (pBlock[-1].u.hdr.size4x&1)!=0 ); + return (pBlock[-1].u.hdr.size4x&~3)*2 - 4; +} + +/* +** Chunk i is a free chunk that has been unlinked. Adjust its +** size parameters for check-out and return a pointer to the +** user portion of the chunk. +*/ +static void *memsys3Checkout(u32 i, int nBlock){ + u32 x; + assert( sqlite3_mutex_held(mem.mutex) ); + assert( i>=1 ); + assert( mem.aPool[i-1].u.hdr.size4x/4==nBlock ); + assert( mem.aPool[i+nBlock-1].u.hdr.prevSize==nBlock ); + x = mem.aPool[i-1].u.hdr.size4x; + mem.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2); + mem.aPool[i+nBlock-1].u.hdr.prevSize = nBlock; + mem.aPool[i+nBlock-1].u.hdr.size4x |= 2; + return &mem.aPool[i]; +} + +/* +** Carve a piece off of the end of the mem.iMaster free chunk. +** Return a pointer to the new allocation. Or, if the master chunk +** is not large enough, return 0. +*/ +static void *memsys3FromMaster(int nBlock){ + assert( sqlite3_mutex_held(mem.mutex) ); + assert( mem.szMaster>=nBlock ); + if( nBlock>=mem.szMaster-1 ){ + /* Use the entire master */ + void *p = memsys3Checkout(mem.iMaster, mem.szMaster); + mem.iMaster = 0; + mem.szMaster = 0; + mem.mnMaster = 0; + return p; + }else{ + /* Split the master block. Return the tail. */ + u32 newi, x; + newi = mem.iMaster + mem.szMaster - nBlock; + assert( newi > mem.iMaster+1 ); + mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = nBlock; + mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x |= 2; + mem.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1; + mem.szMaster -= nBlock; + mem.aPool[newi-1].u.hdr.prevSize = mem.szMaster; + x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; + mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; + if( mem.szMaster < mem.mnMaster ){ + mem.mnMaster = mem.szMaster; + } + return (void*)&mem.aPool[newi]; + } +} + +/* +** *pRoot is the head of a list of free chunks of the same size +** or same size hash. In other words, *pRoot is an entry in either +** mem.aiSmall[] or mem.aiHash[]. +** +** This routine examines all entries on the given list and tries +** to coalesce each entries with adjacent free chunks. +** +** If it sees a chunk that is larger than mem.iMaster, it replaces +** the current mem.iMaster with the new larger chunk. In order for +** this mem.iMaster replacement to work, the master chunk must be +** linked into the hash tables. That is not the normal state of +** affairs, of course. The calling routine must link the master +** chunk before invoking this routine, then must unlink the (possibly +** changed) master chunk once this routine has finished. +*/ +static void memsys3Merge(u32 *pRoot){ + u32 iNext, prev, size, i, x; + + assert( sqlite3_mutex_held(mem.mutex) ); + for(i=*pRoot; i>0; i=iNext){ + iNext = mem.aPool[i].u.list.next; + size = mem.aPool[i-1].u.hdr.size4x; + assert( (size&1)==0 ); + if( (size&2)==0 ){ + memsys3UnlinkFromList(i, pRoot); + assert( i > mem.aPool[i-1].u.hdr.prevSize ); + prev = i - mem.aPool[i-1].u.hdr.prevSize; + if( prev==iNext ){ + iNext = mem.aPool[prev].u.list.next; + } + memsys3Unlink(prev); + size = i + size/4 - prev; + x = mem.aPool[prev-1].u.hdr.size4x & 2; + mem.aPool[prev-1].u.hdr.size4x = size*4 | x; + mem.aPool[prev+size-1].u.hdr.prevSize = size; + memsys3Link(prev); + i = prev; + }else{ + size /= 4; + } + if( size>mem.szMaster ){ + mem.iMaster = i; + mem.szMaster = size; + } + } +} + +/* +** Return a block of memory of at least nBytes in size. +** Return NULL if unable. +*/ +static void *memsys3Malloc(int nByte){ + u32 i; + int nBlock; + int toFree; + + assert( sqlite3_mutex_held(mem.mutex) ); + assert( sizeof(Mem3Block)==8 ); + if( nByte<=12 ){ + nBlock = 2; + }else{ + nBlock = (nByte + 11)/8; + } + assert( nBlock >= 2 ); + + /* STEP 1: + ** Look for an entry of the correct size in either the small + ** chunk table or in the large chunk hash table. This is + ** successful most of the time (about 9 times out of 10). + */ + if( nBlock <= MX_SMALL ){ + i = mem.aiSmall[nBlock-2]; + if( i>0 ){ + memsys3UnlinkFromList(i, &mem.aiSmall[nBlock-2]); + return memsys3Checkout(i, nBlock); + } + }else{ + int hash = nBlock % N_HASH; + for(i=mem.aiHash[hash]; i>0; i=mem.aPool[i].u.list.next){ + if( mem.aPool[i-1].u.hdr.size4x/4==nBlock ){ + memsys3UnlinkFromList(i, &mem.aiHash[hash]); + return memsys3Checkout(i, nBlock); + } + } + } + + /* STEP 2: + ** Try to satisfy the allocation by carving a piece off of the end + ** of the master chunk. This step usually works if step 1 fails. + */ + if( mem.szMaster>=nBlock ){ + return memsys3FromMaster(nBlock); + } + + + /* STEP 3: + ** Loop through the entire memory pool. Coalesce adjacent free + ** chunks. Recompute the master chunk as the largest free chunk. + ** Then try again to satisfy the allocation by carving a piece off + ** of the end of the master chunk. This step happens very + ** rarely (we hope!) + */ + for(toFree=nBlock*16; toFree=nBlock ){ + return memsys3FromMaster(nBlock); + } + } + } + + /* If none of the above worked, then we fail. */ + return 0; +} + +/* +** Free an outstanding memory allocation. +*/ +void memsys3Free(void *pOld){ + Mem3Block *p = (Mem3Block*)pOld; + int i; + u32 size, x; + assert( sqlite3_mutex_held(mem.mutex) ); + assert( p>mem.aPool && p<&mem.aPool[SQLITE_MEMORY_SIZE/8] ); + i = p - mem.aPool; + assert( (mem.aPool[i-1].u.hdr.size4x&1)==1 ); + size = mem.aPool[i-1].u.hdr.size4x/4; + assert( i+size<=SQLITE_MEMORY_SIZE/8+1 ); + mem.aPool[i-1].u.hdr.size4x &= ~1; + mem.aPool[i+size-1].u.hdr.prevSize = size; + mem.aPool[i+size-1].u.hdr.size4x &= ~2; + memsys3Link(i); + + /* Try to expand the master using the newly freed chunk */ + if( mem.iMaster ){ + while( (mem.aPool[mem.iMaster-1].u.hdr.size4x&2)==0 ){ + size = mem.aPool[mem.iMaster-1].u.hdr.prevSize; + mem.iMaster -= size; + mem.szMaster += size; + memsys3Unlink(mem.iMaster); + x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; + mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; + mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; + } + x = mem.aPool[mem.iMaster-1].u.hdr.size4x & 2; + while( (mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x&1)==0 ){ + memsys3Unlink(mem.iMaster+mem.szMaster); + mem.szMaster += mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.size4x/4; + mem.aPool[mem.iMaster-1].u.hdr.size4x = mem.szMaster*4 | x; + mem.aPool[mem.iMaster+mem.szMaster-1].u.hdr.prevSize = mem.szMaster; + } + } +} + +/* +** Allocate nBytes of memory +*/ +void *sqlite3_malloc(int nBytes){ + sqlite3_int64 *p = 0; + if( nBytes>0 ){ + memsys3Enter(); + p = memsys3Malloc(nBytes); + sqlite3_mutex_leave(mem.mutex); + } + return (void*)p; +} + +/* +** Free memory. +*/ +void sqlite3_free(void *pPrior){ + if( pPrior==0 ){ + return; + } + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + memsys3Free(pPrior); + sqlite3_mutex_leave(mem.mutex); +} + +/* +** Change the size of an existing memory allocation +*/ +void *sqlite3_realloc(void *pPrior, int nBytes){ + int nOld; + void *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + assert( mem.mutex!=0 ); + nOld = memsys3Size(pPrior); + if( nBytes<=nOld && nBytes>=nOld-128 ){ + return pPrior; + } + sqlite3_mutex_enter(mem.mutex); + p = memsys3Malloc(nBytes); + if( p ){ + if( nOld>1)!=(size&1) ){ + fprintf(out, "%p tail checkout bit is incorrect\n", &mem.aPool[i]); + assert( 0 ); + break; + } + if( size&1 ){ + fprintf(out, "%p %6d bytes checked out\n", &mem.aPool[i], (size/4)*8-8); + }else{ + fprintf(out, "%p %6d bytes free%s\n", &mem.aPool[i], (size/4)*8-8, + i==mem.iMaster ? " **master**" : ""); + } + } + for(i=0; i0; j=mem.aPool[j].u.list.next){ + fprintf(out, " %p(%d)", &mem.aPool[j], + (mem.aPool[j-1].u.hdr.size4x/4)*8-8); + } + fprintf(out, "\n"); + } + for(i=0; i0; j=mem.aPool[j].u.list.next){ + fprintf(out, " %p(%d)", &mem.aPool[j], + (mem.aPool[j-1].u.hdr.size4x/4)*8-8); + } + fprintf(out, "\n"); + } + fprintf(out, "master=%d\n", mem.iMaster); + fprintf(out, "nowUsed=%d\n", SQLITE_MEMORY_SIZE - mem.szMaster*8); + fprintf(out, "mxUsed=%d\n", SQLITE_MEMORY_SIZE - mem.mnMaster*8); + sqlite3_mutex_leave(mem.mutex); + if( out==stdout ){ + fflush(stdout); + }else{ + fclose(out); + } +#endif +} + + +#endif /* !SQLITE_MEMORY_SIZE */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mem4.c b/client/src/thirdparty/sqlite-3.4.2/src/mem4.c new file mode 100644 index 0000000..7d861d4 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mem4.c @@ -0,0 +1,398 @@ +/* +** 2007 August 14 +** +** 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 the C functions that implement a memory +** allocation subsystem for use by SQLite. +** +** $Id: mem4.c,v 1.1 2007/11/29 18:36:49 drh Exp $ +*/ + +/* +** This version of the memory allocator attempts to obtain memory +** from mmap() if the size of the allocation is close to the size +** of a virtual memory page. If the size of the allocation is different +** from the virtual memory page size, then ordinary malloc() is used. +** Ordinary malloc is also used if space allocated to mmap() is +** exhausted. +** +** Enable this memory allocation by compiling with -DSQLITE_MMAP_HEAP_SIZE=nnn +** where nnn is the maximum number of bytes of mmap-ed memory you want +** to support. This module may choose to use less memory than requested. +** +*/ +#if defined(SQLITE_MMAP_HEAP_SIZE) + +#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) +# error cannot use SQLITE_MMAP_HEAP_SIZE with either SQLITE_MEMDEBUG \ + or SQLITE_MEMORY_SIZE +#endif + +/* +** This is a test version of the memory allocator that attempts to +** use mmap() and madvise() for allocations and frees of approximately +** the virtual memory page size. +*/ +#include +#include +#include +#include "sqliteInt.h" +#include + + +/* +** All of the static variables used by this module are collected +** into a single structure named "mem". This is to keep the +** static variables organized and to reduce namespace pollution +** when this module is combined with other in the amalgamation. +*/ +static struct { + /* + ** The alarm callback and its arguments. The mem.mutex lock will + ** be held while the callback is running. Recursive calls into + ** the memory subsystem are allowed, but no new callbacks will be + ** issued. The alarmBusy variable is set to prevent recursive + ** callbacks. + */ + sqlite3_int64 alarmThreshold; + void (*alarmCallback)(void*, sqlite3_int64,int); + void *alarmArg; + int alarmBusy; + + /* + ** Mutex to control access to the memory allocation subsystem. + */ + sqlite3_mutex *mutex; + + /* + ** Current allocation and high-water mark. + */ + sqlite3_int64 nowUsed; + sqlite3_int64 mxUsed; + + /* + ** Current allocation and high-water marks for mmap allocated memory. + */ + sqlite3_int64 nowUsedMMap; + sqlite3_int64 mxUsedMMap; + + /* + ** Size of a single mmap page. Obtained from sysconf(). + */ + int szPage; + int mnPage; + + /* + ** The number of available mmap pages. + */ + int nPage; + + /* + ** Index of the first free page. 0 means no pages have been freed. + */ + int firstFree; + + /* First unused page on the top of the heap. + */ + int firstUnused; + + /* + ** Bulk memory obtained from from mmap(). + */ + char *mmapHeap; /* first byte of the heap */ + +} mem; + + +/* +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. +** The mmap() region is initialized the first time this routine is called. +*/ +static void memsys4Enter(void){ + if( mem.mutex==0 ){ + mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); + } + sqlite3_mutex_enter(mem.mutex); +} + +/* +** Attempt to free memory to the mmap heap. This only works if +** the pointer p is within the range of memory addresses that +** comprise the mmap heap. Return 1 if the memory was freed +** successfully. Return 0 if the pointer is out of range. +*/ +static int mmapFree(void *p){ + char *z; + int idx, *a; + if( mem.mmapHeap==MAP_FAILED || mem.nPage==0 ){ + return 0; + } + z = (char*)p; + idx = (z - mem.mmapHeap)/mem.szPage; + if( idx<1 || idx>=mem.nPage ){ + return 0; + } + a = (int*)mem.mmapHeap; + a[idx] = a[mem.firstFree]; + mem.firstFree = idx; + mem.nowUsedMMap -= mem.szPage; + madvise(p, mem.szPage, MADV_DONTNEED); + return 1; +} + +/* +** Attempt to allocate nBytes from the mmap heap. Return a pointer +** to the allocated page. Or, return NULL if the allocation fails. +** +** The allocation will fail if nBytes is not the right size. +** Or, the allocation will fail if the mmap heap has been exhausted. +*/ +static void *mmapAlloc(int nBytes){ + int idx = 0; + if( nBytes>mem.szPage || nBytes mem.szPage ){ + mem.nPage = mem.szPage/sizeof(int); + } + mem.mmapHeap = mmap(0, mem.szPage*mem.nPage, PROT_WRITE|PROT_READ, + MAP_ANONYMOUS|MAP_SHARED, -1, 0); + if( mem.mmapHeap==MAP_FAILED ){ + mem.firstUnused = errno; + }else{ + mem.firstUnused = 1; + mem.nowUsedMMap = mem.szPage; + } + } + if( mem.mmapHeap==MAP_FAILED ){ + return 0; + } + if( mem.firstFree ){ + int idx = mem.firstFree; + int *a = (int*)mem.mmapHeap; + mem.firstFree = a[idx]; + }else if( mem.firstUnusedmem.mxUsedMMap ){ + mem.mxUsedMMap = mem.nowUsedMMap; + } + return (void*)&mem.mmapHeap[idx*mem.szPage]; + }else{ + return 0; + } +} + +/* +** Release the mmap-ed memory region if it is currently allocated and +** is not in use. +*/ +static void mmapUnmap(void){ + if( mem.mmapHeap==MAP_FAILED ) return; + if( mem.nPage==0 ) return; + if( mem.nowUsedMMap>mem.szPage ) return; + munmap(mem.mmapHeap, mem.nPage*mem.szPage); + mem.nowUsedMMap = 0; + mem.nPage = 0; +} + + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + memsys4Enter(); + n = mem.nowUsed + mem.nowUsedMMap; + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Return the maximum amount of memory that has ever been +** checked out since either the beginning of this process +** or since the most recent reset. +*/ +sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ + sqlite3_int64 n; + memsys4Enter(); + n = mem.mxUsed + mem.mxUsedMMap; + if( resetFlag ){ + mem.mxUsed = mem.nowUsed; + mem.mxUsedMMap = mem.nowUsedMMap; + } + sqlite3_mutex_leave(mem.mutex); + return n; +} + +/* +** Change the alarm callback +*/ +int sqlite3_memory_alarm( + void(*xCallback)(void *pArg, sqlite3_int64 used,int N), + void *pArg, + sqlite3_int64 iThreshold +){ + memsys4Enter(); + mem.alarmCallback = xCallback; + mem.alarmArg = pArg; + mem.alarmThreshold = iThreshold; + sqlite3_mutex_leave(mem.mutex); + return SQLITE_OK; +} + +/* +** Trigger the alarm +*/ +static void sqlite3MemsysAlarm(int nByte){ + void (*xCallback)(void*,sqlite3_int64,int); + sqlite3_int64 nowUsed; + void *pArg; + if( mem.alarmCallback==0 || mem.alarmBusy ) return; + mem.alarmBusy = 1; + xCallback = mem.alarmCallback; + nowUsed = mem.nowUsed; + pArg = mem.alarmArg; + sqlite3_mutex_leave(mem.mutex); + xCallback(pArg, nowUsed, nByte); + sqlite3_mutex_enter(mem.mutex); + mem.alarmBusy = 0; +} + +/* +** Allocate nBytes of memory +*/ +static void *memsys4Malloc(int nBytes){ + sqlite3_int64 *p = 0; + if( mem.alarmCallback!=0 + && mem.nowUsed+mem.nowUsedMMap+nBytes>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes); + } + if( (p = mmapAlloc(nBytes))==0 ){ + p = malloc(nBytes+8); + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = malloc(nBytes+8); + } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + } + return (void*)p; +} + +/* +** Return the size of a memory allocation +*/ +static int memsys4Size(void *pPrior){ + char *z = (char*)pPrior; + int idx = mem.nPage ? (z - mem.mmapHeap)/mem.szPage : 0; + int nByte; + if( idx>=1 && idx0 ){ + memsys4Enter(); + p = memsys4Malloc(nBytes); + sqlite3_mutex_leave(mem.mutex); + } + return (void*)p; +} + +/* +** Free memory. +*/ +void sqlite3_free(void *pPrior){ + if( pPrior==0 ){ + return; + } + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + memsys4Free(pPrior); + sqlite3_mutex_leave(mem.mutex); +} + + + +/* +** Change the size of an existing memory allocation +*/ +void *sqlite3_realloc(void *pPrior, int nBytes){ + int nOld; + sqlite3_int64 *p; + if( pPrior==0 ){ + return sqlite3_malloc(nBytes); + } + if( nBytes<=0 ){ + sqlite3_free(pPrior); + return 0; + } + nOld = memsys4Size(pPrior); + if( nBytes<=nOld && nBytes>=nOld-128 ){ + return pPrior; + } + assert( mem.mutex!=0 ); + sqlite3_mutex_enter(mem.mutex); + p = memsys4Malloc(nBytes); + if( p ){ + if( nOldid = id; + pNew->cnt = 0; + } + break; + } + default: { + assert( id-2 >= 0 ); + assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) ); + pNew = &aStatic[id-2]; + pNew->id = id; + break; + } + } + return pNew; +} + +/* +** This routine deallocates a previously allocated mutex. +*/ +void sqlite3_mutex_free(sqlite3_mutex *p){ + assert( p ); + assert( p->cnt==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + sqlite3_free(p); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +void sqlite3_mutex_enter(sqlite3_mutex *p){ + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + p->cnt++; +} +int sqlite3_mutex_try(sqlite3_mutex *p){ + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + p->cnt++; + return SQLITE_OK; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +void sqlite3_mutex_leave(sqlite3_mutex *p){ + assert( p ); + assert( sqlite3_mutex_held(p) ); + p->cnt--; + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); +} + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +int sqlite3_mutex_held(sqlite3_mutex *p){ + return p==0 || p->cnt>0; +} +int sqlite3_mutex_notheld(sqlite3_mutex *p){ + return p==0 || p->cnt==0; +} +#endif /* SQLITE_MUTEX_NOOP_DEBUG */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mutex.h b/client/src/thirdparty/sqlite-3.4.2/src/mutex.h new file mode 100644 index 0000000..e7ec9d2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mutex.h @@ -0,0 +1,82 @@ +/* +** 2007 August 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 contains the common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +** +** $Id: mutex.h,v 1.2 2007/08/30 14:10:30 drh Exp $ +*/ + + +#ifdef SQLITE_MUTEX_APPDEF +/* +** If SQLITE_MUTEX_APPDEF is defined, then this whole module is +** omitted and equivalent functionality must be provided by the +** application that links against the SQLite library. +*/ +#else +/* +** Figure out what version of the code to use. The choices are +** +** SQLITE_MUTEX_NOOP For single-threaded applications that +** do not desire error checking. +** +** SQLITE_MUTEX_NOOP_DEBUG For single-threaded applications with +** error checking to help verify that mutexes +** are being used correctly even though they +** are not needed. Used when SQLITE_DEBUG is +** defined on single-threaded builds. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. +** +** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. +*/ +#define SQLITE_MUTEX_NOOP 1 /* The default */ +#if defined(SQLITE_DEBUG) && !SQLITE_THREADSAFE +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_NOOP_DEBUG +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_UNIX +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_PTHREADS +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_WIN +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_W32 +#endif +#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && OS_OS2 +# undef SQLITE_MUTEX_NOOP +# define SQLITE_MUTEX_OS2 +#endif + +#ifdef SQLITE_MUTEX_NOOP +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) 1 +#define sqlite3_mutex_notheld(X) 1 +#endif + +#endif /* SQLITE_MUTEX_APPDEF */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mutex_os2.c b/client/src/thirdparty/sqlite-3.4.2/src/mutex_os2.c new file mode 100644 index 0000000..cbffeee --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mutex_os2.c @@ -0,0 +1,245 @@ +/* +** 2007 August 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 contains the C functions that implement mutexes for OS/2 +** +** $Id: mutex_os2.c,v 1.5 2008/02/01 19:42:38 pweilbacher Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if SQLITE_MUTEX_OS2 is defined. +** See the mutex.h file for details. +*/ +#ifdef SQLITE_MUTEX_OS2 + +/********************** OS/2 Mutex Implementation ********************** +** +** This implementation of mutexes is built using the OS/2 API. +*/ + +/* +** The mutex object +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + HMTX mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + int nRef; /* Number of references */ + TID owner; /* Thread holding this mutex */ +}; + +#define OS2_MUTEX_INITIALIZER 0,0,0,0 + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. +** SQLite will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST 0 +**
  • SQLITE_MUTEX_RECURSIVE 1 +**
  • SQLITE_MUTEX_STATIC_MASTER 2 +**
  • SQLITE_MUTEX_STATIC_MEM 3 +**
  • SQLITE_MUTEX_STATIC_PRNG 4 +**
+** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Three static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int iType){ + sqlite3_mutex *p = NULL; + switch( iType ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + if( DosCreateMutexSem( 0, &p->mutex, 0, FALSE ) != NO_ERROR ){ + sqlite3_free( p ); + p = NULL; + } + } + break; + } + default: { + static volatile int isInit = 0; + static sqlite3_mutex staticMutexes[] = { + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + { OS2_MUTEX_INITIALIZER, }, + }; + if ( !isInit ){ + APIRET rc; + PTIB ptib; + PPIB ppib; + HMTX mutex; + char name[32]; + DosGetInfoBlocks( &ptib, &ppib ); + sqlite3_snprintf( sizeof(name), name, "\\SEM32\\SQLITE%04x", + ppib->pib_ulpid ); + while( !isInit ){ + mutex = 0; + rc = DosCreateMutexSem( name, &mutex, 0, FALSE); + if( rc == NO_ERROR ){ + int i; + if( !isInit ){ + for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){ + DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE ); + } + isInit = 1; + } + DosCloseMutexSem( mutex ); + }else if( rc == ERROR_DUPLICATE_NAME ){ + DosSleep( 1 ); + }else{ + return p; + } + } + } + assert( iType-2 >= 0 ); + assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + p = &staticMutexes[iType-2]; + p->id = iType; + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously allocated mutex. +** SQLite is careful to deallocate every mutex that it allocates. +*/ +void sqlite3_mutex_free(sqlite3_mutex *p){ + assert( p ); + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + DosCloseMutexSem( p->mutex ); + sqlite3_free( p ); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +void sqlite3_mutex_enter(sqlite3_mutex *p){ + TID tid; + PID holder1; + ULONG holder2; + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT); + DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); + p->owner = tid; + p->nRef++; +} +int sqlite3_mutex_try(sqlite3_mutex *p){ + int rc; + TID tid; + PID holder1; + ULONG holder2; + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) { + DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); + p->owner = tid; + p->nRef++; + rc = SQLITE_OK; + } else { + rc = SQLITE_BUSY; + } + + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +void sqlite3_mutex_leave(sqlite3_mutex *p){ + TID tid; + PID holder1; + ULONG holder2; + assert( p->nRef>0 ); + DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2); + assert( p->owner==tid ); + p->nRef--; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + DosReleaseMutexSem(p->mutex); +} + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use inside assert() statements. +*/ +int sqlite3_mutex_held(sqlite3_mutex *p){ + TID tid; + PID pid; + ULONG ulCount; + PTIB ptib; + if( p!=0 ) { + DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); + } else { + DosGetInfoBlocks(&ptib, NULL); + tid = ptib->tib_ptib2->tib2_ultid; + } + return p==0 || (p->nRef!=0 && p->owner==tid); +} +int sqlite3_mutex_notheld(sqlite3_mutex *p){ + TID tid; + PID pid; + ULONG ulCount; + PTIB ptib; + if( p!= 0 ) { + DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount); + } else { + DosGetInfoBlocks(&ptib, NULL); + tid = ptib->tib_ptib2->tib2_ultid; + } + return p==0 || p->nRef==0 || p->owner!=tid; +} +#endif /* SQLITE_MUTEX_OS2 */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mutex_unix.c b/client/src/thirdparty/sqlite-3.4.2/src/mutex_unix.c new file mode 100644 index 0000000..93e7e9a --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mutex_unix.c @@ -0,0 +1,298 @@ +/* +** 2007 August 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 contains the C functions that implement mutexes for pthreads +** +** $Id: mutex_unix.c,v 1.5 2007/11/28 14:04:57 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if we are compiling threadsafe +** under unix with pthreads. +** +** Note that this implementation requires a version of pthreads that +** supports recursive mutexes. +*/ +#ifdef SQLITE_MUTEX_PTHREADS + +#include + + +/* +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + pthread_mutex_t mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + int nRef; /* Number of entrances */ + pthread_t owner; /* Thread that is within this mutex */ +#ifdef SQLITE_DEBUG + int trace; /* True to trace changes */ +#endif +}; + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. SQLite +** will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_MEM2 +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
+** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Three static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int iType){ + static sqlite3_mutex staticMutexes[] = { + { PTHREAD_MUTEX_INITIALIZER, }, + { PTHREAD_MUTEX_INITIALIZER, }, + { PTHREAD_MUTEX_INITIALIZER, }, + { PTHREAD_MUTEX_INITIALIZER, }, + { PTHREAD_MUTEX_INITIALIZER, }, + }; + sqlite3_mutex *p; + switch( iType ){ + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, we will have to + ** build our own. See below. */ + pthread_mutex_init(&p->mutex, 0); +#else + /* Use a recursive mutex if it is available */ + pthread_mutexattr_t recursiveAttr; + pthread_mutexattr_init(&recursiveAttr); + pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&p->mutex, &recursiveAttr); + pthread_mutexattr_destroy(&recursiveAttr); +#endif + p->id = iType; + } + break; + } + case SQLITE_MUTEX_FAST: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + pthread_mutex_init(&p->mutex, 0); + } + break; + } + default: { + assert( iType-2 >= 0 ); + assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + p = &staticMutexes[iType-2]; + p->id = iType; + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously +** allocated mutex. SQLite is careful to deallocate every +** mutex that it allocates. +*/ +void sqlite3_mutex_free(sqlite3_mutex *p){ + assert( p ); + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + pthread_mutex_destroy(&p->mutex); + sqlite3_free(p); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +void sqlite3_mutex_enter(sqlite3_mutex *p){ + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, then we have to grow + ** our own. This implementation assumes that pthread_equal() + ** is atomic - that it cannot be deceived into thinking self + ** and p->owner are equal if p->owner changes between two values + ** that are not equal to self while the comparison is taking place. + ** This implementation also assumes a coherent cache - that + ** separate processes cannot read different values from the same + ** address at the same time. If either of these two conditions + ** are not met, then the mutexes will fail and problems will result. + */ + { + pthread_t self = pthread_self(); + if( p->nRef>0 && pthread_equal(p->owner, self) ){ + p->nRef++; + }else{ + pthread_mutex_lock(&p->mutex); + assert( p->nRef==0 ); + p->owner = self; + p->nRef = 1; + } + } +#else + /* Use the built-in recursive mutexes if they are available. + */ + pthread_mutex_lock(&p->mutex); + p->owner = pthread_self(); + p->nRef++; +#endif + +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif +} +int sqlite3_mutex_try(sqlite3_mutex *p){ + int rc; + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + /* If recursive mutexes are not available, then we have to grow + ** our own. This implementation assumes that pthread_equal() + ** is atomic - that it cannot be deceived into thinking self + ** and p->owner are equal if p->owner changes between two values + ** that are not equal to self while the comparison is taking place. + ** This implementation also assumes a coherent cache - that + ** separate processes cannot read different values from the same + ** address at the same time. If either of these two conditions + ** are not met, then the mutexes will fail and problems will result. + */ + { + pthread_t self = pthread_self(); + if( p->nRef>0 && pthread_equal(p->owner, self) ){ + p->nRef++; + rc = SQLITE_OK; + }else if( pthread_mutex_lock(&p->mutex)==0 ){ + assert( p->nRef==0 ); + p->owner = self; + p->nRef = 1; + rc = SQLITE_OK; + }else{ + rc = SQLITE_BUSY; + } + } +#else + /* Use the built-in recursive mutexes if they are available. + */ + if( pthread_mutex_trylock(&p->mutex)==0 ){ + p->owner = pthread_self(); + p->nRef++; + rc = SQLITE_OK; + }else{ + rc = SQLITE_BUSY; + } +#endif + +#ifdef SQLITE_DEBUG + if( rc==SQLITE_OK && p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +void sqlite3_mutex_leave(sqlite3_mutex *p){ + assert( p ); + assert( sqlite3_mutex_held(p) ); + p->nRef--; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + +#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX + if( p->nRef==0 ){ + pthread_mutex_unlock(&p->mutex); + } +#else + pthread_mutex_unlock(&p->mutex); +#endif + +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif +} + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. On some platforms, +** there might be race conditions that can cause these routines to +** deliver incorrect results. In particular, if pthread_equal() is +** not an atomic operation, then these routines might delivery +** incorrect results. On most platforms, pthread_equal() is a +** comparison of two integers and is therefore atomic. But we are +** told that HPUX is not such a platform. If so, then these routines +** will not always work correctly on HPUX. +** +** On those platforms where pthread_equal() is not atomic, SQLite +** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to +** make sure no assert() statements are evaluated and hence these +** routines are never called. +*/ +#ifndef NDEBUG +int sqlite3_mutex_held(sqlite3_mutex *p){ + return p==0 || (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); +} +int sqlite3_mutex_notheld(sqlite3_mutex *p){ + return p==0 || p->nRef==0 || pthread_equal(p->owner, pthread_self())==0; +} +#endif +#endif /* SQLITE_MUTEX_PTHREAD */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/mutex_w32.c b/client/src/thirdparty/sqlite-3.4.2/src/mutex_w32.c new file mode 100644 index 0000000..1944ccc --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/mutex_w32.c @@ -0,0 +1,219 @@ +/* +** 2007 August 14 +** +** 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 the C functions that implement mutexes for win32 +** +** $Id: mutex_w32.c,v 1.5 2007/10/05 15:08:01 drh Exp $ +*/ +#include "sqliteInt.h" + +/* +** The code in this file is only used if we are compiling multithreaded +** on a win32 system. +*/ +#ifdef SQLITE_MUTEX_W32 + +/* +** Each recursive mutex is an instance of the following structure. +*/ +struct sqlite3_mutex { + CRITICAL_SECTION mutex; /* Mutex controlling the lock */ + int id; /* Mutex type */ + int nRef; /* Number of enterances */ + DWORD owner; /* Thread holding this mutex */ +}; + +/* +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, +** or WinCE. Return false (zero) for Win95, Win98, or WinME. +** +** Here is an interesting observation: Win95, Win98, and WinME lack +** the LockFileEx() API. But we can still statically link against that +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ +#if OS_WINCE +# define mutexIsNT() (1) +#else + static int mutexIsNT(void){ + static int osType = 0; + if( osType==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return osType==2; + } +#endif /* OS_WINCE */ + + +/* +** The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. If it returns NULL +** that means that a mutex could not be allocated. SQLite +** will unwind its stack and return an error. The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST 0 +**
  • SQLITE_MUTEX_RECURSIVE 1 +**
  • SQLITE_MUTEX_STATIC_MASTER 2 +**
  • SQLITE_MUTEX_STATIC_MEM 3 +**
  • SQLITE_MUTEX_STATIC_PRNG 4 +**
+** +** The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. But SQLite will only request a recursive mutex in +** cases where it really needs one. If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. Three static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int iType){ + sqlite3_mutex *p; + + switch( iType ){ + case SQLITE_MUTEX_FAST: + case SQLITE_MUTEX_RECURSIVE: { + p = sqlite3MallocZero( sizeof(*p) ); + if( p ){ + p->id = iType; + InitializeCriticalSection(&p->mutex); + } + break; + } + default: { + static sqlite3_mutex staticMutexes[5]; + static int isInit = 0; + while( !isInit ){ + static long lock = 0; + if( InterlockedIncrement(&lock)==1 ){ + int i; + for(i=0; i= 0 ); + assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + p = &staticMutexes[iType-2]; + p->id = iType; + break; + } + } + return p; +} + + +/* +** This routine deallocates a previously +** allocated mutex. SQLite is careful to deallocate every +** mutex that it allocates. +*/ +void sqlite3_mutex_free(sqlite3_mutex *p){ + assert( p ); + assert( p->nRef==0 ); + assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); + DeleteCriticalSection(&p->mutex); + sqlite3_free(p); +} + +/* +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can +** be entered multiple times by the same thread. In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. If the same thread tries to enter any other kind of mutex +** more than once, the behavior is undefined. +*/ +void sqlite3_mutex_enter(sqlite3_mutex *p){ + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + EnterCriticalSection(&p->mutex); + p->owner = GetCurrentThreadId(); + p->nRef++; +} +int sqlite3_mutex_try(sqlite3_mutex *p){ + int rc = SQLITE_BUSY; + assert( p ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || sqlite3_mutex_notheld(p) ); + /* + ** The sqlite3_mutex_try() routine is very rarely used, and when it + ** is used it is merely an optimization. So it is OK for it to always + ** fail. + ** + ** The TryEnterCriticalSection() interface is only available on WinNT. + ** And some windows compilers complain if you try to use it without + ** first doing some #defines that prevent SQLite from building on Win98. + ** For that reason, we will omit this optimization for now. See + ** ticket #2685. + */ +#if 0 + if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){ + p->owner = GetCurrentThreadId(); + p->nRef++; + rc = SQLITE_OK; + } +#endif + return rc; +} + +/* +** The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. The behavior +** is undefined if the mutex is not currently entered or +** is not currently allocated. SQLite will never do either. +*/ +void sqlite3_mutex_leave(sqlite3_mutex *p){ + assert( p->nRef>0 ); + assert( p->owner==GetCurrentThreadId() ); + p->nRef--; + assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); + LeaveCriticalSection(&p->mutex); +} + +/* +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are +** intended for use only inside assert() statements. +*/ +int sqlite3_mutex_held(sqlite3_mutex *p){ + return p==0 || (p->nRef!=0 && p->owner==GetCurrentThreadId()); +} +int sqlite3_mutex_notheld(sqlite3_mutex *p){ + return p==0 || p->nRef==0 || p->owner!=GetCurrentThreadId(); +} +#endif /* SQLITE_MUTEX_W32 */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os.c b/client/src/thirdparty/sqlite-3.4.2/src/os.c new file mode 100644 index 0000000..57e2d0f --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os.c @@ -0,0 +1,267 @@ + /* +** 2005 November 29 +** +** 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 OS interface code that is common to all +** architectures. +*/ +#define _SQLITE_OS_C_ 1 +#include "sqliteInt.h" +#undef _SQLITE_OS_C_ + +/* +** The default SQLite sqlite3_vfs implementations do not allocate +** memory (actually, os_unix.c allocates a small amount of memory +** from within OsOpen()), but some third-party implementations may. +** So we test the effects of a malloc() failing and the sqlite3OsXXX() +** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro. +** +** The following functions are instrumented for malloc() failure +** testing: +** +** sqlite3OsOpen() +** sqlite3OsRead() +** sqlite3OsWrite() +** sqlite3OsSync() +** sqlite3OsLock() +** +*/ +#ifdef SQLITE_TEST + #define DO_OS_MALLOC_TEST if (1) { \ + void *pTstAlloc = sqlite3_malloc(10); \ + if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ + sqlite3_free(pTstAlloc); \ + } +#else + #define DO_OS_MALLOC_TEST +#endif + +/* +** The following routines are convenience wrappers around methods +** of the sqlite3_file object. This is mostly just syntactic sugar. All +** of this would be completely automatic if SQLite were coded using +** C++ instead of plain old C. +*/ +int sqlite3OsClose(sqlite3_file *pId){ + int rc = SQLITE_OK; + if( pId->pMethods ){ + rc = pId->pMethods->xClose(pId); + pId->pMethods = 0; + } + return rc; +} +int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){ + DO_OS_MALLOC_TEST; + return id->pMethods->xRead(id, pBuf, amt, offset); +} +int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){ + DO_OS_MALLOC_TEST; + return id->pMethods->xWrite(id, pBuf, amt, offset); +} +int sqlite3OsTruncate(sqlite3_file *id, i64 size){ + return id->pMethods->xTruncate(id, size); +} +int sqlite3OsSync(sqlite3_file *id, int flags){ + DO_OS_MALLOC_TEST; + return id->pMethods->xSync(id, flags); +} +int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){ + return id->pMethods->xFileSize(id, pSize); +} +int sqlite3OsLock(sqlite3_file *id, int lockType){ + DO_OS_MALLOC_TEST; + return id->pMethods->xLock(id, lockType); +} +int sqlite3OsUnlock(sqlite3_file *id, int lockType){ + return id->pMethods->xUnlock(id, lockType); +} +int sqlite3OsCheckReservedLock(sqlite3_file *id){ + return id->pMethods->xCheckReservedLock(id); +} +int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ + return id->pMethods->xFileControl(id,op,pArg); +} +int sqlite3OsSectorSize(sqlite3_file *id){ + int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize; + return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE); +} +int sqlite3OsDeviceCharacteristics(sqlite3_file *id){ + return id->pMethods->xDeviceCharacteristics(id); +} + +/* +** The next group of routines are convenience wrappers around the +** VFS methods. +*/ +int sqlite3OsOpen( + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pFlagsOut +){ + DO_OS_MALLOC_TEST; + return pVfs->xOpen(pVfs, zPath, pFile, flags, pFlagsOut); +} +int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + return pVfs->xDelete(pVfs, zPath, dirSync); +} +int sqlite3OsAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ + return pVfs->xAccess(pVfs, zPath, flags); +} +int sqlite3OsGetTempname(sqlite3_vfs *pVfs, int nBufOut, char *zBufOut){ + return pVfs->xGetTempname(pVfs, nBufOut, zBufOut); +} +int sqlite3OsFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nPathOut, + char *zPathOut +){ + return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut); +} +void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return pVfs->xDlOpen(pVfs, zPath); +} +void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + pVfs->xDlError(pVfs, nByte, zBufOut); +} +void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return pVfs->xDlSym(pVfs, pHandle, zSymbol); +} +void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){ + pVfs->xDlClose(pVfs, pHandle); +} +int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return pVfs->xRandomness(pVfs, nByte, zBufOut); +} +int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){ + return pVfs->xSleep(pVfs, nMicro); +} +int sqlite3OsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return pVfs->xCurrentTime(pVfs, pTimeOut); +} + +int sqlite3OsOpenMalloc( + sqlite3_vfs *pVfs, + const char *zFile, + sqlite3_file **ppFile, + int flags, + int *pOutFlags +){ + int rc = SQLITE_NOMEM; + sqlite3_file *pFile; + pFile = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile); + if( pFile ){ + rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags); + if( rc!=SQLITE_OK ){ + sqlite3_free(pFile); + }else{ + *ppFile = pFile; + } + } + return rc; +} +int sqlite3OsCloseFree(sqlite3_file *pFile){ + int rc = SQLITE_OK; + if( pFile ){ + rc = sqlite3OsClose(pFile); + sqlite3_free(pFile); + } + return rc; +} + +/* +** The list of all registered VFS implementations. This list is +** initialized to the single VFS returned by sqlite3OsDefaultVfs() +** upon the first call to sqlite3_vfs_find(). +*/ +static sqlite3_vfs *vfsList = 0; + +/* +** Locate a VFS by name. If no name is given, simply return the +** first VFS on the list. +*/ +sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_vfs *pVfs = 0; + static int isInit = 0; + sqlite3_mutex_enter(mutex); + if( !isInit ){ + vfsList = sqlite3OsDefaultVfs(); + isInit = 1; + } + for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){ + if( zVfs==0 ) break; + if( strcmp(zVfs, pVfs->zName)==0 ) break; + } + sqlite3_mutex_leave(mutex); + return pVfs; +} + +/* +** Unlink a VFS from the linked list +*/ +static void vfsUnlink(sqlite3_vfs *pVfs){ + assert( sqlite3_mutex_held(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)) ); + if( pVfs==0 ){ + /* No-op */ + }else if( vfsList==pVfs ){ + vfsList = pVfs->pNext; + }else if( vfsList ){ + sqlite3_vfs *p = vfsList; + while( p->pNext && p->pNext!=pVfs ){ + p = p->pNext; + } + if( p->pNext==pVfs ){ + p->pNext = pVfs->pNext; + } + } +} + +/* +** Register a VFS with the system. It is harmless to register the same +** VFS multiple times. The new VFS becomes the default if makeDflt is +** true. +*/ +int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_vfs_find(0); /* Make sure we are initialized */ + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + if( makeDflt || vfsList==0 ){ + pVfs->pNext = vfsList; + vfsList = pVfs; + }else{ + pVfs->pNext = vfsList->pNext; + vfsList->pNext = pVfs; + } + assert(vfsList); + sqlite3_mutex_leave(mutex); + return SQLITE_OK; +} + +/* +** Unregister a VFS so that it is no longer accessible. +*/ +int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){ +#ifndef SQLITE_MUTEX_NOOP + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); +#endif + sqlite3_mutex_enter(mutex); + vfsUnlink(pVfs); + sqlite3_mutex_leave(mutex); + return SQLITE_OK; +} diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os.h b/client/src/thirdparty/sqlite-3.4.2/src/os.h new file mode 100644 index 0000000..026e2c4 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os.h @@ -0,0 +1,275 @@ +/* +** 2001 September 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 header file (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. After the following block of preprocess macros, +** all of OS_UNIX, OS_WIN, OS_OS2, and OS_OTHER will defined to either +** 1 or 0. One of the four will be 1. The other three will be 0. +*/ +#if defined(OS_OTHER) +# if OS_OTHER==1 +# undef OS_UNIX +# define OS_UNIX 0 +# undef OS_WIN +# define OS_WIN 0 +# undef OS_OS2 +# define OS_OS2 0 +# else +# undef OS_OTHER +# endif +#endif +#if !defined(OS_UNIX) && !defined(OS_OTHER) +# define OS_OTHER 0 +# ifndef OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) +# define OS_WIN 1 +# define OS_UNIX 0 +# define OS_OS2 0 +# elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__) +# define OS_WIN 0 +# define OS_UNIX 0 +# define OS_OS2 1 +# else +# define OS_WIN 0 +# define OS_UNIX 1 +# define OS_OS2 0 +# endif +# else +# define OS_UNIX 0 +# define OS_OS2 0 +# endif +#else +# ifndef OS_WIN +# define OS_WIN 0 +# endif +#endif + + + +/* +** Define the maximum size of a temporary filename +*/ +#if OS_WIN +# include +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#elif OS_OS2 +# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) +# include /* has to be included before os2.h for linking to work */ +# endif +# define INCL_DOSDATETIME +# define INCL_DOSFILEMGR +# define INCL_DOSERRORS +# define INCL_DOSMISC +# define INCL_DOSPROCESS +# define INCL_DOSMODULEMGR +# define INCL_DOSSEMAPHORES +# include +# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) +#else +# define SQLITE_TEMPNAME_SIZE 200 +#endif + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 512 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** a random byte is selected for a shared lock. The pool of bytes for +** shared locks begins at SHARED_FIRST. +** +** These #defines are available in sqlite_aux.h so that adaptors for +** connecting SQLite to other operating systems can use the same byte +** ranges for locking. In particular, the same locking strategy and +** byte ranges are used for Unix. This leaves open the possiblity of having +** clients on win95, winNT, and unix all talking to the same shared file +** and all locking correctly. To do so would require that samba (or whatever +** tool is being used for file sharing) implements locks correctly between +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#ifndef SQLITE_TEST +#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */ +#else +extern unsigned int sqlite3_pending_byte; +#define PENDING_BYTE sqlite3_pending_byte +#endif + +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Functions for accessing sqlite3_file methods +*/ +int sqlite3OsClose(sqlite3_file*); +int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +int sqlite3OsTruncate(sqlite3_file*, i64 size); +int sqlite3OsSync(sqlite3_file*, int); +int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +int sqlite3OsLock(sqlite3_file*, int); +int sqlite3OsUnlock(sqlite3_file*, int); +int sqlite3OsCheckReservedLock(sqlite3_file *id); +int sqlite3OsFileControl(sqlite3_file*,int,void*); +int sqlite3OsSectorSize(sqlite3_file *id); +int sqlite3OsDeviceCharacteristics(sqlite3_file *id); + +/* +** Functions for accessing sqlite3_vfs methods +*/ +int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +int sqlite3OsAccess(sqlite3_vfs *, const char *, int); +int sqlite3OsGetTempname(sqlite3_vfs *, int, char *); +int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +void sqlite3OsDlError(sqlite3_vfs *, int, char *); +void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *); +void sqlite3OsDlClose(sqlite3_vfs *, void *); +int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +int sqlite3OsSleep(sqlite3_vfs *, int); +int sqlite3OsCurrentTime(sqlite3_vfs *, double*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +int sqlite3OsCloseFree(sqlite3_file *); + +/* +** Each OS-specific backend defines an instance of the following +** structure for returning a pointer to its sqlite3_vfs. If OS_OTHER +** is defined (meaning that the application-defined OS interface layer +** is used) then there is no default VFS. The application must +** register one or more VFS structures using sqlite3_vfs_register() +** before attempting to use SQLite. +*/ +#if OS_UNIX || OS_WIN || OS_OS2 +sqlite3_vfs *sqlite3OsDefaultVfs(void); +#else +# define sqlite3OsDefaultVfs(X) 0 +#endif + +#endif /* _SQLITE_OS_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_common.h b/client/src/thirdparty/sqlite-3.4.2/src/os_common.h new file mode 100644 index 0000000..8de4be9 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_common.h @@ -0,0 +1,127 @@ +/* +** 2004 May 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 macros and a little bit of code that is common to +** all of the platform-specific files (os_*.c) and is #included into those +** files. +** +** This file should be #included by the os_*.c files only. It is not a +** general purpose header file. +*/ + +/* +** At least two bugs have slipped in because we changed the MEMORY_DEBUG +** macro to SQLITE_DEBUG and some older makefiles have not yet made the +** switch. The following code should catch this problem at compile-time. +*/ +#ifdef MEMORY_DEBUG +# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead." +#endif + + +/* + * When testing, this global variable stores the location of the + * pending-byte in the database file. + */ +#ifdef SQLITE_TEST +unsigned int sqlite3_pending_byte = 0x40000000; +#endif + +#ifdef SQLITE_DEBUG +int sqlite3_os_trace = 0; +#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X) +#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y) +#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) \ + if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) \ + if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D) +#else +#define OSTRACE1(X) +#define OSTRACE2(X,Y) +#define OSTRACE3(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) +#endif + +/* +** Macros for performance tracing. Normally turned off. Only works +** on i486 hardware. +*/ +#ifdef SQLITE_PERFORMANCE_TRACE +__inline__ unsigned long long int hwtime(void){ + unsigned long long int x; + __asm__("rdtsc\n\t" + "mov %%edx, %%ecx\n\t" + :"=A" (x)); + return x; +} +static unsigned long long int g_start; +static unsigned int elapse; +#define TIMER_START g_start=hwtime() +#define TIMER_END elapse=hwtime()-g_start +#define TIMER_ELAPSED elapse +#else +#define TIMER_START +#define TIMER_END +#define TIMER_ELAPSED 0 +#endif + +/* +** If we compile with the SQLITE_TEST macro set, then the following block +** of code will give us the ability to simulate a disk I/O error. This +** is used for testing the I/O recovery logic. +*/ +#ifdef SQLITE_TEST +int sqlite3_io_error_hit = 0; +int sqlite3_io_error_pending = 0; +int sqlite3_io_error_persist = 0; +int sqlite3_diskfull_pending = 0; +int sqlite3_diskfull = 0; +#define SimulateIOError(CODE) \ + if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \ + if( sqlite3_io_error_pending-- == 1 \ + || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit = 1; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 1; \ + CODE; \ + }else{ \ + sqlite3_diskfull_pending--; \ + } \ + } +#else +#define SimulateIOError(A) +#define SimulateDiskfullError(A) +#endif + +/* +** When testing, keep a count of the number of open files. +*/ +#ifdef SQLITE_TEST +int sqlite3_open_file_count = 0; +#define OpenCounter(X) sqlite3_open_file_count+=(X) +#else +#define OpenCounter(X) +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_os2.c b/client/src/thirdparty/sqlite-3.4.2/src/os_os2.c new file mode 100644 index 0000000..d5e3382 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_os2.c @@ -0,0 +1,989 @@ +/* +** 2006 Feb 14 +** +** 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 OS/2. +*/ + +#include "sqliteInt.h" + +#if OS_OS2 + +/* +** A Note About Memory Allocation: +** +** This driver uses malloc()/free() directly rather than going through +** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers +** are designed for use on embedded systems where memory is scarce and +** malloc failures happen frequently. OS/2 does not typically run on +** embedded systems, and when it does the developers normally have bigger +** problems to worry about than running out of memory. So there is not +** a compelling need to use the wrappers. +** +** But there is a good reason to not use the wrappers. If we use the +** wrappers then we will get simulated malloc() failures within this +** driver. And that causes all kinds of problems for our tests. We +** could enhance SQLite to deal with simulated malloc failures within +** the OS driver, but the code to deal with those failure would not +** be exercised on Linux (which does not need to malloc() in the driver) +** and so we would have difficulty writing coverage tests for that +** code. Better to leave the code out, we think. +** +** The point of this discussion is as follows: When creating a new +** OS layer for an embedded system, if you use this file as an example, +** avoid the use of malloc()/free(). Those routines work ok on OS/2 +** desktops but not so well in embedded systems. +*/ + +/* +** Macros used to determine whether or not to use threads. +*/ +#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE +# define SQLITE_OS2_THREADS 1 +#endif + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** The os2File structure is subclass of sqlite3_file specific for the OS/2 +** protability layer. +*/ +typedef struct os2File os2File; +struct os2File { + const sqlite3_io_methods *pMethod; /* Always the first entry */ + HFILE h; /* Handle for accessing the file */ + int delOnClose; /* True if file is to be deleted on close */ + char* pathToDel; /* Name of file to delete on close */ + unsigned char locktype; /* Type of lock currently held on this file */ +}; + +/***************************************************************************** +** The next group of routines implement the I/O methods specified +** by the sqlite3_io_methods object. +******************************************************************************/ + +/* +** Close a file. +*/ +int os2Close( sqlite3_file *id ){ + APIRET rc = NO_ERROR; + os2File *pFile; + if( id && (pFile = (os2File*)id) != 0 ){ + OSTRACE2( "CLOSE %d\n", pFile->h ); + rc = DosClose( pFile->h ); + pFile->locktype = NO_LOCK; + if( pFile->delOnClose != 0 ){ + rc = DosForceDelete( (PSZ)pFile->pathToDel ); + } + if( pFile->pathToDel ){ + free( pFile->pathToDel ); + } + id = 0; + OpenCounter( -1 ); + } + + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +int os2Read( + sqlite3_file *id, /* File to read from */ + void *pBuf, /* Write content into this buffer */ + int amt, /* Number of bytes to read */ + sqlite3_int64 offset /* Begin reading at this offset */ +){ + ULONG fileLocation = 0L; + ULONG got; + os2File *pFile = (os2File*)id; + assert( id!=0 ); + SimulateIOError( return SQLITE_IOERR_READ ); + OSTRACE3( "READ %d lock=%d\n", pFile->h, pFile->locktype ); + if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){ + return SQLITE_IOERR; + } + if( DosRead( pFile->h, pBuf, amt, &got ) != NO_ERROR ){ + return SQLITE_IOERR_READ; + } + if( got == (ULONG)amt ) + return SQLITE_OK; + else { + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +int os2Write( + sqlite3_file *id, /* File to write into */ + const void *pBuf, /* The bytes to be written */ + int amt, /* Number of bytes to write */ + sqlite3_int64 offset /* Offset into the file to begin writing at */ +){ + ULONG fileLocation = 0L; + APIRET rc = NO_ERROR; + ULONG wrote; + os2File *pFile = (os2File*)id; + assert( id!=0 ); + SimulateIOError( return SQLITE_IOERR_WRITE ); + SimulateDiskfullError( return SQLITE_FULL ); + OSTRACE3( "WRITE %d lock=%d\n", pFile->h, pFile->locktype ); + if( DosSetFilePtr(pFile->h, offset, FILE_BEGIN, &fileLocation) != NO_ERROR ){ + return SQLITE_IOERR; + } + assert( amt>0 ); + while( amt > 0 && + (rc = DosWrite( pFile->h, (PVOID)pBuf, amt, &wrote )) && + wrote > 0 + ){ + amt -= wrote; + pBuf = &((char*)pBuf)[wrote]; + } + + return ( rc != NO_ERROR || amt > (int)wrote ) ? SQLITE_FULL : SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +int os2Truncate( sqlite3_file *id, i64 nByte ){ + APIRET rc = NO_ERROR; + os2File *pFile = (os2File*)id; + OSTRACE3( "TRUNCATE %d %lld\n", pFile->h, nByte ); + SimulateIOError( return SQLITE_IOERR_TRUNCATE ); + rc = DosSetFileSize( pFile->h, nByte ); + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +int sqlite3_sync_count = 0; +int sqlite3_fullsync_count = 0; +#endif + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +int os2Sync( sqlite3_file *id, int flags ){ + os2File *pFile = (os2File*)id; + OSTRACE3( "SYNC %d lock=%d\n", pFile->h, pFile->locktype ); +#ifdef SQLITE_TEST + if( flags & SQLITE_SYNC_FULL){ + sqlite3_fullsync_count++; + } + sqlite3_sync_count++; +#endif + return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Determine the current size of a file in bytes +*/ +int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){ + APIRET rc = NO_ERROR; + FILESTATUS3 fsts3FileInfo; + memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo)); + assert( id!=0 ); + SimulateIOError( return SQLITE_IOERR ); + rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) ); + if( rc == NO_ERROR ){ + *pSize = fsts3FileInfo.cbFile; + return SQLITE_OK; + }else{ + return SQLITE_IOERR; + } +} + +/* +** Acquire a reader lock. +*/ +static int getReadLock( os2File *pFile ){ + FILELOCK LockArea, + UnlockArea; + APIRET res; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + LockArea.lOffset = SHARED_FIRST; + LockArea.lRange = SHARED_SIZE; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "GETREADLOCK %d res=%d\n", pFile->h, res ); + return res; +} + +/* +** Undo a readlock +*/ +static int unlockReadLock( os2File *id ){ + FILELOCK LockArea, + UnlockArea; + APIRET res; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = SHARED_FIRST; + UnlockArea.lRange = SHARED_SIZE; + res = DosSetFileLocks( id->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "UNLOCK-READLOCK file handle=%d res=%d?\n", id->h, res ); + return res; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. The os2Unlock() routine +** erases all locks at once and returns us immediately to locking level 0. +** It is not possible to lower the locking level one step at a time. You +** must go straight to locking level 0. +*/ +int os2Lock( sqlite3_file *id, int locktype ){ + int rc = SQLITE_OK; /* Return code from subroutines */ + APIRET res = NO_ERROR; /* Result of an OS/2 lock call */ + int newLocktype; /* Set pFile->locktype to this value before exiting */ + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + FILELOCK LockArea, + UnlockArea; + os2File *pFile = (os2File*)id; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + assert( pFile!=0 ); + OSTRACE4( "LOCK %d %d was %d\n", pFile->h, locktype, pFile->locktype ); + + /* If there is already a lock of this type or more restrictive on the + ** os2File, do nothing. Don't use the end_lock: exit path, as + ** sqlite3OsEnterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3( "LOCK %d %d ok (already held)\n", pFile->h, locktype ); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or + ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of + ** the PENDING_LOCK byte is temporary. + */ + newLocktype = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) + ){ + int cnt = 3; + + LockArea.lOffset = PENDING_BYTE; + LockArea.lRange = 1L; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + + while( cnt-->0 && ( res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) ) + != NO_ERROR + ){ + /* Try 3 times to get the pending lock. The pending lock might be + ** held by another reader process who will release it momentarily. + */ + OSTRACE2( "LOCK could not get a PENDING lock. cnt=%d\n", cnt ); + DosSleep(1); + } + if( res == NO_ERROR){ + gotPendingLock = 1; + OSTRACE3( "LOCK %d pending lock boolean set. res=%d\n", pFile->h, res ); + } + } + + /* Acquire a shared lock + */ + if( locktype==SHARED_LOCK && res == NO_ERROR ){ + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); + if( res == NO_ERROR ){ + newLocktype = SHARED_LOCK; + } + OSTRACE3( "LOCK %d acquire shared lock. res=%d\n", pFile->h, res ); + } + + /* Acquire a RESERVED lock + */ + if( locktype==RESERVED_LOCK && res == NO_ERROR ){ + assert( pFile->locktype==SHARED_LOCK ); + LockArea.lOffset = RESERVED_BYTE; + LockArea.lRange = 1L; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + if( res == NO_ERROR ){ + newLocktype = RESERVED_LOCK; + } + OSTRACE3( "LOCK %d acquire reserved lock. res=%d\n", pFile->h, res ); + } + + /* Acquire a PENDING lock + */ + if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){ + newLocktype = PENDING_LOCK; + gotPendingLock = 0; + OSTRACE2( "LOCK %d acquire pending lock. pending lock boolean unset.\n", pFile->h ); + } + + /* Acquire an EXCLUSIVE lock + */ + if( locktype==EXCLUSIVE_LOCK && res == NO_ERROR ){ + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); + OSTRACE2( "unreadlock = %d\n", res ); + LockArea.lOffset = SHARED_FIRST; + LockArea.lRange = SHARED_SIZE; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + if( res == NO_ERROR ){ + newLocktype = EXCLUSIVE_LOCK; + }else{ + OSTRACE2( "OS/2 error-code = %d\n", res ); + getReadLock(pFile); + } + OSTRACE3( "LOCK %d acquire exclusive lock. res=%d\n", pFile->h, res ); + } + + /* If we are holding a PENDING lock that ought to be released, then + ** release it now. + */ + if( gotPendingLock && locktype==SHARED_LOCK ){ + int r; + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = PENDING_BYTE; + UnlockArea.lRange = 1L; + r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "LOCK %d unlocking pending/is shared. r=%d\n", pFile->h, r ); + } + + /* Update the state of the lock has held in the file descriptor then + ** return the appropriate result code. + */ + if( res == NO_ERROR ){ + rc = SQLITE_OK; + }else{ + OSTRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h, + locktype, newLocktype ); + rc = SQLITE_BUSY; + } + pFile->locktype = newLocktype; + OSTRACE3( "LOCK %d now %d\n", pFile->h, pFile->locktype ); + return rc; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero, otherwise zero. +*/ +int os2CheckReservedLock( sqlite3_file *id ){ + APIRET rc = NO_ERROR; + os2File *pFile = (os2File*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ + rc = 1; + OSTRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc ); + }else{ + FILELOCK LockArea, + UnlockArea; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + LockArea.lOffset = RESERVED_BYTE; + LockArea.lRange = 1L; + UnlockArea.lOffset = 0L; + UnlockArea.lRange = 0L; + rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "TEST WR-LOCK %d lock reserved byte rc=%d\n", pFile->h, rc ); + if( rc == NO_ERROR ){ + int r; + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = RESERVED_BYTE; + UnlockArea.lRange = 1L; + r = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "TEST WR-LOCK %d unlock reserved byte r=%d\n", pFile->h, r ); + } + OSTRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc ); + } + return rc; +} + +/* +** Lower the locking level on file descriptor id to locktype. locktype +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +** +** It is not possible for this routine to fail if the second argument +** is NO_LOCK. If the second argument is SHARED_LOCK then this routine +** might return SQLITE_IOERR; +*/ +int os2Unlock( sqlite3_file *id, int locktype ){ + int type; + os2File *pFile = (os2File*)id; + APIRET rc = SQLITE_OK; + APIRET res = NO_ERROR; + FILELOCK LockArea, + UnlockArea; + memset(&LockArea, 0, sizeof(LockArea)); + memset(&UnlockArea, 0, sizeof(UnlockArea)); + assert( pFile!=0 ); + assert( locktype<=SHARED_LOCK ); + OSTRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ); + type = pFile->locktype; + if( type>=EXCLUSIVE_LOCK ){ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = SHARED_FIRST; + UnlockArea.lRange = SHARED_SIZE; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "UNLOCK %d exclusive lock res=%d\n", pFile->h, res ); + if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){ + /* This should never happen. We should always be able to + ** reacquire the read lock */ + OSTRACE3( "UNLOCK %d to %d getReadLock() failed\n", pFile->h, locktype ); + rc = SQLITE_IOERR_UNLOCK; + } + } + if( type>=RESERVED_LOCK ){ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = RESERVED_BYTE; + UnlockArea.lRange = 1L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "UNLOCK %d reserved res=%d\n", pFile->h, res ); + } + if( locktype==NO_LOCK && type>=SHARED_LOCK ){ + res = unlockReadLock(pFile); + OSTRACE5( "UNLOCK %d is %d want %d res=%d\n", pFile->h, type, locktype, res ); + } + if( type>=PENDING_LOCK ){ + LockArea.lOffset = 0L; + LockArea.lRange = 0L; + UnlockArea.lOffset = PENDING_BYTE; + UnlockArea.lRange = 1L; + res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); + OSTRACE3( "UNLOCK %d pending res=%d\n", pFile->h, res ); + } + pFile->locktype = locktype; + OSTRACE3( "UNLOCK %d now %d\n", pFile->h, pFile->locktype ); + return rc; +} + +/* +** Control and query of the open file handle. +*/ +static int os2FileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = ((os2File*)id)->locktype; + OSTRACE3( "FCNTL_LOCKSTATE %d lock=%d\n", ((os2File*)id)->h, ((os2File*)id)->locktype ); + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int os2SectorSize(sqlite3_file *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return a vector of device characteristics. +*/ +static int os2DeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for os2. +*/ +static const sqlite3_io_methods os2IoMethod = { + 1, /* iVersion */ + os2Close, + os2Read, + os2Write, + os2Truncate, + os2Sync, + os2FileSize, + os2Lock, + os2Unlock, + os2CheckReservedLock, + os2FileControl, + os2SectorSize, + os2DeviceCharacteristics +}; + +/*************************************************************************** +** Here ends the I/O methods that form the sqlite3_io_methods object. +** +** The next block of code implements the VFS methods. +****************************************************************************/ + +/* +** Open a file. +*/ +static int os2Open( + sqlite3_vfs *pVfs, /* Not used */ + const char *zName, /* Name of the file */ + sqlite3_file *id, /* Write the SQLite file handle here */ + int flags, /* Open mode flags */ + int *pOutFlags /* Status return flags */ +){ + HFILE h; + ULONG ulFileAttribute = 0; + ULONG ulOpenFlags = 0; + ULONG ulOpenMode = 0; + os2File *pFile = (os2File*)id; + APIRET rc = NO_ERROR; + ULONG ulAction; + + memset(pFile, 0, sizeof(*pFile)); + + OSTRACE2( "OPEN want %d\n", flags ); + + //ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY; + if( flags & SQLITE_OPEN_READWRITE ){ + ulOpenMode |= OPEN_ACCESS_READWRITE; + OSTRACE1( "OPEN read/write\n" ); + }else{ + ulOpenMode |= OPEN_ACCESS_READONLY; + OSTRACE1( "OPEN read only\n" ); + } + + //ulOpenFlags = flags & SQLITE_OPEN_CREATE ? OPEN_ACTION_CREATE_IF_NEW : OPEN_ACTION_FAIL_IF_NEW; + if( flags & SQLITE_OPEN_CREATE ){ + ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; + OSTRACE1( "OPEN open new/create\n" ); + }else{ + ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; + OSTRACE1( "OPEN open existing\n" ); + } + + //ulOpenMode |= flags & SQLITE_OPEN_MAIN_DB ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYWRITE; + if( flags & SQLITE_OPEN_MAIN_DB ){ + ulOpenMode |= OPEN_SHARE_DENYNONE; + OSTRACE1( "OPEN share read/write\n" ); + }else{ + ulOpenMode |= OPEN_SHARE_DENYWRITE; + OSTRACE1( "OPEN share read only\n" ); + } + + if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL + | SQLITE_OPEN_SUBJOURNAL) ){ + //ulFileAttribute = FILE_HIDDEN; //for debugging, we want to make sure it is deleted + ulFileAttribute = FILE_NORMAL; + pFile->delOnClose = 1; + pFile->pathToDel = (char*)malloc(sizeof(char) * pVfs->mxPathname); + sqlite3OsFullPathname(pVfs, zName, pVfs->mxPathname, pFile->pathToDel); + OSTRACE1( "OPEN hidden/delete on close file attributes\n" ); + }else{ + ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL; + pFile->delOnClose = 0; + pFile->pathToDel = NULL; + OSTRACE1( "OPEN normal file attribute\n" ); + } + + //ulOpenMode |= flags & (SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB) ? + // OPEN_FLAGS_RANDOM : OPEN_FLAGS_SEQUENTIAL; + if( flags & (SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB) ){ + ulOpenMode |= OPEN_FLAGS_RANDOM; + OSTRACE1( "OPEN random access\n" ); + }else{ + ulOpenMode |= OPEN_FLAGS_SEQUENTIAL; + OSTRACE1( "OPEN sequential access\n" ); + } + ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR; + + rc = DosOpen( (PSZ)zName, + &h, + &ulAction, + 0L, + ulFileAttribute, + ulOpenFlags, + ulOpenMode, + (PEAOP2)NULL ); + if( rc != NO_ERROR ){ + OSTRACE7( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n", + rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ); + if( flags & SQLITE_OPEN_READWRITE ){ + OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ); + return os2Open( 0, zName, id, + ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE), + pOutFlags ); + }else{ + return SQLITE_CANTOPEN; + } + } + + if( pOutFlags ){ + *pOutFlags = flags & SQLITE_OPEN_READWRITE ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY; + } + + pFile->pMethod = &os2IoMethod; + pFile->h = h; + OpenCounter(+1); + OSTRACE3( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ); + return SQLITE_OK; +} + +/* +** Delete the named file. +*/ +int os2Delete( + sqlite3_vfs *pVfs, /* Not used on os2 */ + const char *zFilename, /* Name of file to delete */ + int syncDir /* Not used on os2 */ +){ + APIRET rc = NO_ERROR; + SimulateIOError(return SQLITE_IOERR_DELETE); + rc = DosDelete( (PSZ)zFilename ); + OSTRACE2( "DELETE \"%s\"\n", zFilename ); + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Check the existance and status of a file. +*/ +static int os2Access( + sqlite3_vfs *pVfs, /* Not used on os2 */ + const char *zFilename, /* Name of file to check */ + int flags /* Type of test to make on this file */ +){ + FILESTATUS3 fsts3ConfigInfo; + APIRET rc = NO_ERROR; + + memset(&fsts3ConfigInfo, 0, sizeof(fsts3ConfigInfo)); + rc = DosQueryPathInfo( (PSZ)zFilename, FIL_STANDARD, + &fsts3ConfigInfo, sizeof(FILESTATUS3) ); + OSTRACE4( "ACCESS fsts3ConfigInfo.attrFile=%d flags=%d rc=%d\n", + fsts3ConfigInfo.attrFile, flags, rc ); + switch( flags ){ + case SQLITE_ACCESS_READ: + case SQLITE_ACCESS_EXISTS: + rc = (rc == NO_ERROR); + OSTRACE3( "ACCESS %s access of read and exists rc=%d\n", zFilename, rc ); + break; + case SQLITE_ACCESS_READWRITE: + rc = (fsts3ConfigInfo.attrFile & FILE_READONLY) == 0; + OSTRACE3( "ACCESS %s access of read/write rc=%d\n", zFilename, rc ); + break; + default: + assert( !"Invalid flags argument" ); + } + return rc; +} + + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at pVfs->mxPathname characters. +*/ +static int os2GetTempname( sqlite3_vfs *pVfs, int nBuf, char *zBuf ){ + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + char zTempPathBuf[3]; + PSZ zTempPath = (PSZ)&zTempPathBuf; + if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){ + if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){ + if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){ + ULONG ulDriveNum = 0, ulDriveMap = 0; + DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ); + sprintf( (char*)zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) ); + } + } + } + /* strip off a trailing slashes or backslashes, otherwise we would get * + * multiple (back)slashes which causes DosOpen() to fail */ + j = strlen(zTempPath); + while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/' ) ){ + j--; + } + zTempPath[j] = '\0'; + sqlite3_snprintf( nBuf-30, zBuf, + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath ); + j = strlen( zBuf ); + sqlite3Randomness( 20, &zBuf[j] ); + for( i = 0; i < 20; i++, j++ ){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + OSTRACE2( "TEMP FILENAME: %s\n", zBuf ); + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. Write the full +** pathname into zFull[]. zFull[] will be at least pVfs->mxPathname +** bytes in size. +*/ +static int os2FullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + APIRET rc = DosQueryPathInfo( zRelative, FIL_QUERYFULLNAME, zFull, nFull ); + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; +} + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +static void *os2DlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + UCHAR loadErr[256]; + HMODULE hmod; + APIRET rc; + rc = DosLoadModule((PSZ)loadErr, sizeof(loadErr), zFilename, &hmod); + return rc != NO_ERROR ? 0 : (void*)hmod; +} +/* +** A no-op since the error code is returned on the DosLoadModule call. +** os2Dlopen returns zero if DosLoadModule is not successful. +*/ +static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ +/* no-op */ +} +void *os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + PFN pfn; + APIRET rc; + rc = DosQueryProcAddr((HMODULE)pHandle, 0L, zSymbol, &pfn); + if( rc != NO_ERROR ){ + /* if the symbol itself was not found, search again for the same + * symbol with an extra underscore, that might be needed depending + * on the calling convention */ + char _zSymbol[256] = "_"; + strncat(_zSymbol, zSymbol, 255); + rc = DosQueryProcAddr((HMODULE)pHandle, 0L, _zSymbol, &pfn); + } + return rc != NO_ERROR ? 0 : (void*)pfn; +} +void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){ + DosFreeModule((HMODULE)pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define os2DlOpen 0 + #define os2DlError 0 + #define os2DlSym 0 + #define os2DlClose 0 +#endif + + +/* +** Write up to nBuf bytes of randomness into zBuf. +*/ +static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){ + ULONG sizeofULong = sizeof(ULONG); + int n = 0; + if( sizeof(DATETIME) <= nBuf - n ){ + DATETIME x; + DosGetDateTime(&x); + memcpy(&zBuf[n], &x, sizeof(x)); + n += sizeof(x); + } + + if( sizeofULong <= nBuf - n ){ + PPIB ppib; + DosGetInfoBlocks(NULL, &ppib); + memcpy(&zBuf[n], &ppib->pib_ulpid, sizeofULong); + n += sizeofULong; + } + + if( sizeofULong <= nBuf - n ){ + PTIB ptib; + DosGetInfoBlocks(&ptib, NULL); + memcpy(&zBuf[n], &ptib->tib_ptib2->tib2_ultid, sizeofULong); + n += sizeofULong; + } + + /* if we still haven't filled the buffer yet the following will */ + /* grab everything once instead of making several calls for a single item */ + if( sizeofULong <= nBuf - n ){ + ULONG ulSysInfo[QSV_MAX]; + DosQuerySysInfo(1L, QSV_MAX, ulSysInfo, sizeofULong * QSV_MAX); + + memcpy(&zBuf[n], &ulSysInfo[QSV_MS_COUNT - 1], sizeofULong); + n += sizeofULong; + + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TIMER_INTERVAL - 1], sizeofULong); + n += sizeofULong; + } + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TIME_LOW - 1], sizeofULong); + n += sizeofULong; + } + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TIME_HIGH - 1], sizeofULong); + n += sizeofULong; + } + if( sizeofULong <= nBuf - n ){ + memcpy(&zBuf[n], &ulSysInfo[QSV_TOTAVAILMEM - 1], sizeofULong); + n += sizeofULong; + } + } + + return n; +} + +/* +** Sleep for a little while. Return the amount of time slept. +** The argument is the number of microseconds we want to sleep. +** The return value is the number of microseconds of sleep actually +** requested from the underlying operating system, a number which +** might be greater than or equal to the argument, but not less +** than the argument. +*/ +static int os2Sleep( sqlite3_vfs *pVfs, int microsec ){ + DosSleep( (microsec/1000) ); + return microsec; +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){ + double now; + SHORT minute; /* needs to be able to cope with negative timezone offset */ + USHORT second, hour, + day, month, year; + DATETIME dt; + DosGetDateTime( &dt ); + second = (USHORT)dt.seconds; + minute = (SHORT)dt.minutes + dt.timezone; + hour = (USHORT)dt.hours; + day = (USHORT)dt.day; + month = (USHORT)dt.month; + year = (USHORT)dt.year; + + /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html + http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */ + /* Calculate the Julian days */ + now = day - 32076 + + 1461*(year + 4800 + (month - 14)/12)/4 + + 367*(month - 2 - (month - 14)/12*12)/12 - + 3*((year + 4900 + (month - 14)/12)/100)/4; + + /* Add the fractional hours, mins and seconds */ + now += (hour + 12.0)/24.0; + now += minute/1440.0; + now += second/86400.0; + *prNow = now; +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +/* +** Return a pointer to the sqlite3DefaultVfs structure. We use +** a function rather than give the structure global scope because +** some compilers (MSVC) do not allow forward declarations of +** initialized structures. +*/ +sqlite3_vfs *sqlite3OsDefaultVfs(void){ + static sqlite3_vfs os2Vfs = { + 1, /* iVersion */ + sizeof(os2File), /* szOsFile */ + CCHMAXPATH, /* mxPathname */ + 0, /* pNext */ + "os2", /* zName */ + 0, /* pAppData */ + + os2Open, /* xOpen */ + os2Delete, /* xDelete */ + os2Access, /* xAccess */ + os2GetTempname, /* xGetTempname */ + os2FullPathname, /* xFullPathname */ + os2DlOpen, /* xDlOpen */ + os2DlError, /* xDlError */ + os2DlSym, /* xDlSym */ + os2DlClose, /* xDlClose */ + os2Randomness, /* xRandomness */ + os2Sleep, /* xSleep */ + os2CurrentTime /* xCurrentTime */ + }; + + return &os2Vfs; +} + +#endif /* OS_OS2 */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_os2.h b/client/src/thirdparty/sqlite-3.4.2/src/os_os2.h new file mode 100644 index 0000000..de7f385 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_os2.h @@ -0,0 +1,73 @@ +/* +** 2004 May 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 header file defined OS-specific features for OS/2. +*/ +#ifndef _SQLITE_OS_OS2_H_ +#define _SQLITE_OS_OS2_H_ + +/* +** standard include files. +*/ +#include +#include +#include +#include + +/* +** Macros used to determine whether or not to use threads. The +** SQLITE_OS2_THREADS macro is defined if we are synchronizing for +** Posix threads and SQLITE_W32_THREADS is defined if we are +** synchronizing using Win32 threads. +*/ +/* this mutex implementation only available with EMX */ +#if SQLITE_THREADSAFE +# include +# include +# define SQLITE_OS2_THREADS 1 +#endif + +/* +** The OsFile structure is a operating-system independing representation +** of an open file handle. It is defined differently for each architecture. +** +** This is the definition for Unix. +** +** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK, +** PENDING_LOCK or EXCLUSIVE_LOCK. +*/ +typedef struct OsFile OsFile; +struct OsFile { + int h; /* The file descriptor (LHANDLE) */ + int locked; /* True if this user holds the lock */ + int delOnClose; /* True if file is to be deleted on close */ + char *pathToDel; /* Name of file to delete on close */ + unsigned char locktype; /* The type of lock held on this fd */ + unsigned char isOpen; /* True if needs to be closed */ + unsigned char fullSync; +}; + +/* +** Maximum number of characters in a temporary file name +*/ +#define SQLITE_TEMPNAME_SIZE 200 + +/* +** Minimum interval supported by sqlite3OsSleep(). +*/ +#define SQLITE_MIN_SLEEP_MS 1 + +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0600 +#endif + +#endif /* _SQLITE_OS_OS2_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_test.c b/client/src/thirdparty/sqlite-3.4.2/src/os_test.c new file mode 100644 index 0000000..9b1c0e2 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_test.c @@ -0,0 +1,463 @@ +/* +** 2004 May 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 that is specific to Unix systems. It is used +** for testing SQLite only. +*/ +#if OS_TEST /* This file is used for the test backend only */ +#include "sqliteInt.h" +#include "os.h" /* Must be first to enable large file support */ + +#define sqlite3OsOpenReadWrite sqlite3RealOpenReadWrite +#define sqlite3OsOpenExclusive sqlite3RealOpenExclusive +#define sqlite3OsOpenReadOnly sqlite3RealOpenReadOnly +#define sqlite3OsOpenDirectory sqlite3RealOpenDirectory +#define sqlite3OsClose sqlite3RealClose +#define sqlite3OsRead sqlite3RealRead +#define sqlite3OsWrite sqlite3RealWrite +#define sqlite3OsSeek sqlite3RealSeek +#define sqlite3OsSync sqlite3RealSync +#define sqlite3OsTruncate sqlite3RealTruncate +#define sqlite3OsFileSize sqlite3RealFileSize +#define sqlite3OsLock sqlite3RealLock +#define sqlite3OsUnlock sqlite3RealUnlock +#define sqlite3OsCheckReservedLock sqlite3RealCheckReservedLock + +#define OsFile OsRealFile +#define OS_UNIX 1 +#include "os_unix.c" +#undef OS_UNIX +#undef OsFile + +#undef sqlite3OsOpenReadWrite +#undef sqlite3OsOpenExclusive +#undef sqlite3OsOpenReadOnly +#undef sqlite3OsOpenDirectory +#undef sqlite3OsClose +#undef sqlite3OsRead +#undef sqlite3OsWrite +#undef sqlite3OsSeek +#undef sqlite3OsSync +#undef sqlite3OsTruncate +#undef sqlite3OsFileSize +#undef sqlite3OsLock +#undef sqlite3OsUnlock +#undef sqlite3OsCheckReservedLock + +#define BLOCKSIZE 512 +#define BLOCK_OFFSET(x) ((x) * BLOCKSIZE) + + +/* +** The following variables control when a simulated crash occurs. +** +** If iCrashDelay is non-zero, then zCrashFile contains (full path) name of +** a file that SQLite will call sqlite3OsSync() on. Each time this happens +** iCrashDelay is decremented. If iCrashDelay is zero after being +** decremented, a "crash" occurs during the sync() operation. +** +** In other words, a crash occurs the iCrashDelay'th time zCrashFile is +** synced. +*/ +static int iCrashDelay = 0; +char zCrashFile[256]; + +/* +** Set the value of the two crash parameters. +*/ +void sqlite3SetCrashParams(int iDelay, char const *zFile){ + sqlite3OsEnterMutex(); + assert( strlen(zFile)<256 ); + strcpy(zCrashFile, zFile); + iCrashDelay = iDelay; + sqlite3OsLeaveMutex(); +} + +/* +** File zPath is being sync()ed. Return non-zero if this should +** cause a crash. +*/ +static int crashRequired(char const *zPath){ + int r; + int n; + sqlite3OsEnterMutex(); + n = strlen(zCrashFile); + if( zCrashFile[n-1]=='*' ){ + n--; + }else if( strlen(zPath)>n ){ + n = strlen(zPath); + } + r = 0; + if( iCrashDelay>0 && strncmp(zPath, zCrashFile, n)==0 ){ + iCrashDelay--; + if( iCrashDelay<=0 ){ + r = 1; + } + } + sqlite3OsLeaveMutex(); + return r; +} + + +static OsTestFile *pAllFiles = 0; + +/* +** Initialise the os_test.c specific fields of pFile. +*/ +static void initFile(OsFile *id, char const *zName){ + OsTestFile *pFile = (OsTestFile *) + sqliteMalloc(sizeof(OsTestFile) + strlen(zName)+1); + pFile->nMaxWrite = 0; + pFile->nBlk = 0; + pFile->apBlk = 0; + pFile->zName = (char *)(&pFile[1]); + strcpy(pFile->zName, zName); + *id = pFile; + pFile->pNext = pAllFiles; + pAllFiles = pFile; +} + +/* +** Undo the work done by initFile. Delete the OsTestFile structure +** and unlink the structure from the pAllFiles list. +*/ +static void closeFile(OsFile *id){ + OsTestFile *pFile = *id; + if( pFile==pAllFiles ){ + pAllFiles = pFile->pNext; + }else{ + OsTestFile *p; + for(p=pAllFiles; p->pNext!=pFile; p=p->pNext ){ + assert( p ); + } + p->pNext = pFile->pNext; + } + sqliteFree(pFile); + *id = 0; +} + +/* +** Return the current seek offset from the start of the file. This +** is unix-only code. +*/ +static i64 osTell(OsTestFile *pFile){ + return lseek(pFile->fd.h, 0, SEEK_CUR); +} + +/* +** Load block 'blk' into the cache of pFile. +*/ +static int cacheBlock(OsTestFile *pFile, int blk){ + if( blk>=pFile->nBlk ){ + int n = ((pFile->nBlk * 2) + 100 + blk); + /* if( pFile->nBlk==0 ){ printf("DIRTY %s\n", pFile->zName); } */ + pFile->apBlk = (u8 **)sqliteRealloc(pFile->apBlk, n * sizeof(u8*)); + if( !pFile->apBlk ) return SQLITE_NOMEM; + memset(&pFile->apBlk[pFile->nBlk], 0, (n - pFile->nBlk)*sizeof(u8*)); + pFile->nBlk = n; + } + + if( !pFile->apBlk[blk] ){ + i64 filesize; + int rc; + + u8 *p = sqliteMalloc(BLOCKSIZE); + if( !p ) return SQLITE_NOMEM; + pFile->apBlk[blk] = p; + + rc = sqlite3RealFileSize(&pFile->fd, &filesize); + if( rc!=SQLITE_OK ) return rc; + + if( BLOCK_OFFSET(blk)fd, blk*BLOCKSIZE); + if( BLOCK_OFFSET(blk+1)>filesize ){ + len = filesize - BLOCK_OFFSET(blk); + } + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3RealRead(&pFile->fd, p, len); + if( rc!=SQLITE_OK ) return rc; + } + } + + return SQLITE_OK; +} + +/* #define TRACE_WRITECACHE */ + +/* +** Write the cache of pFile to disk. If crash is non-zero, randomly +** skip blocks when writing. The cache is deleted before returning. +*/ +static int writeCache2(OsTestFile *pFile, int crash){ + int i; + int nMax = pFile->nMaxWrite; + i64 offset; + int rc = SQLITE_OK; + + offset = osTell(pFile); + for(i=0; inBlk; i++){ + u8 *p = pFile->apBlk[i]; + if( p ){ + int skip = 0; + int trash = 0; + if( crash ){ + char random; + sqlite3Randomness(1, &random); + if( random & 0x01 ){ + if( random & 0x02 ){ + trash = 1; +#ifdef TRACE_WRITECACHE +printf("Trashing block %d of %s\n", i, pFile->zName); +#endif + }else{ + skip = 1; +#ifdef TRACE_WRITECACHE +printf("Skiping block %d of %s\n", i, pFile->zName); +#endif + } + }else{ +#ifdef TRACE_WRITECACHE +printf("Writing block %d of %s\n", i, pFile->zName); +#endif + } + } + if( rc==SQLITE_OK ){ + rc = sqlite3RealSeek(&pFile->fd, BLOCK_OFFSET(i)); + } + if( rc==SQLITE_OK && !skip ){ + int len = BLOCKSIZE; + if( BLOCK_OFFSET(i+1)>nMax ){ + len = nMax-BLOCK_OFFSET(i); + } + if( len>0 ){ + if( trash ){ + sqlite3Randomness(len, p); + } + rc = sqlite3RealWrite(&pFile->fd, p, len); + } + } + sqliteFree(p); + } + } + sqliteFree(pFile->apBlk); + pFile->nBlk = 0; + pFile->apBlk = 0; + pFile->nMaxWrite = 0; + + if( rc==SQLITE_OK ){ + rc = sqlite3RealSeek(&pFile->fd, offset); + } + return rc; +} + +/* +** Write the cache to disk. +*/ +static int writeCache(OsTestFile *pFile){ + if( pFile->apBlk ){ + int c = crashRequired(pFile->zName); + if( c ){ + OsTestFile *p; +#ifdef TRACE_WRITECACHE + printf("\nCrash during sync of %s\n", pFile->zName); +#endif + for(p=pAllFiles; p; p=p->pNext){ + writeCache2(p, 1); + } + exit(-1); + }else{ + return writeCache2(pFile, 0); + } + } + return SQLITE_OK; +} + +/* +** Close the file. +*/ +int sqlite3OsClose(OsFile *id){ + if( !(*id) ) return SQLITE_OK; + if( (*id)->fd.isOpen ){ + /* printf("CLOSE %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */ + writeCache(*id); + sqlite3RealClose(&(*id)->fd); + } + closeFile(id); + return SQLITE_OK; +} + +int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ + i64 offset; /* The current offset from the start of the file */ + i64 end; /* The byte just past the last byte read */ + int blk; /* Block number the read starts on */ + int i; + u8 *zCsr; + int rc = SQLITE_OK; + OsTestFile *pFile = *id; + + offset = osTell(pFile); + end = offset+amt; + blk = (offset/BLOCKSIZE); + + zCsr = (u8 *)pBuf; + for(i=blk; i*BLOCKSIZE end ){ + len = len - (BLOCK_OFFSET(i+1)-end); + } + + if( inBlk && pFile->apBlk[i]){ + u8 *pBlk = pFile->apBlk[i]; + memcpy(zCsr, &pBlk[off], len); + }else{ + rc = sqlite3RealSeek(&pFile->fd, BLOCK_OFFSET(i) + off); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3RealRead(&pFile->fd, zCsr, len); + if( rc!=SQLITE_OK ) return rc; + } + + zCsr += len; + } + assert( zCsr==&((u8 *)pBuf)[amt] ); + + rc = sqlite3RealSeek(&pFile->fd, end); + return rc; +} + +int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ + i64 offset; /* The current offset from the start of the file */ + i64 end; /* The byte just past the last byte written */ + int blk; /* Block number the write starts on */ + int i; + const u8 *zCsr; + int rc = SQLITE_OK; + OsTestFile *pFile = *id; + + offset = osTell(pFile); + end = offset+amt; + blk = (offset/BLOCKSIZE); + + zCsr = (u8 *)pBuf; + for(i=blk; i*BLOCKSIZEapBlk[i]; + assert( pBlk ); + + if( BLOCK_OFFSET(i) < offset ){ + off = offset-BLOCK_OFFSET(i); + } + len = BLOCKSIZE - off; + if( BLOCK_OFFSET(i+1) > end ){ + len = len - (BLOCK_OFFSET(i+1)-end); + } + memcpy(&pBlk[off], zCsr, len); + zCsr += len; + } + if( pFile->nMaxWritenMaxWrite = end; + } + assert( zCsr==&((u8 *)pBuf)[amt] ); + + rc = sqlite3RealSeek(&pFile->fd, end); + return rc; +} + +/* +** Sync the file. First flush the write-cache to disk, then call the +** real sync() function. +*/ +int sqlite3OsSync(OsFile *id, int dataOnly){ + int rc; + /* printf("SYNC %s (%d blocks)\n", (*id)->zName, (*id)->nBlk); */ + rc = writeCache(*id); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3RealSync(&(*id)->fd, dataOnly); + return rc; +} + +/* +** Truncate the file. Set the internal OsFile.nMaxWrite variable to the new +** file size to ensure that nothing in the write-cache past this point +** is written to disk. +*/ +int sqlite3OsTruncate(OsFile *id, i64 nByte){ + (*id)->nMaxWrite = nByte; + return sqlite3RealTruncate(&(*id)->fd, nByte); +} + +/* +** Return the size of the file. If the cache contains a write that extended +** the file, then return this size instead of the on-disk size. +*/ +int sqlite3OsFileSize(OsFile *id, i64 *pSize){ + int rc = sqlite3RealFileSize(&(*id)->fd, pSize); + if( rc==SQLITE_OK && pSize && *pSize<(*id)->nMaxWrite ){ + *pSize = (*id)->nMaxWrite; + } + return rc; +} + +/* +** The three functions used to open files. All that is required is to +** initialise the os_test.c specific fields and then call the corresponding +** os_unix.c function to really open the file. +*/ +int sqlite3OsOpenReadWrite(const char *zFilename, OsFile *id, int *pReadonly){ + initFile(id, zFilename); + return sqlite3RealOpenReadWrite(zFilename, &(*id)->fd, pReadonly); +} +int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ + initFile(id, zFilename); + return sqlite3RealOpenExclusive(zFilename, &(*id)->fd, delFlag); +} +int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ + initFile(id, zFilename); + return sqlite3RealOpenReadOnly(zFilename, &(*id)->fd); +} + +/* +** These six function calls are passed straight through to the os_unix.c +** backend. +*/ +int sqlite3OsSeek(OsFile *id, i64 offset){ + return sqlite3RealSeek(&(*id)->fd, offset); +} +int sqlite3OsCheckReservedLock(OsFile *id){ + return sqlite3RealCheckReservedLock(&(*id)->fd); +} +int sqlite3OsLock(OsFile *id, int locktype){ + return sqlite3RealLock(&(*id)->fd, locktype); +} +int sqlite3OsUnlock(OsFile *id, int locktype){ + return sqlite3RealUnlock(&(*id)->fd, locktype); +} +int sqlite3OsOpenDirectory(const char *zDirname, OsFile *id){ + return sqlite3RealOpenDirectory(zDirname, &(*id)->fd); +} + +#endif /* OS_TEST */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_test.h b/client/src/thirdparty/sqlite-3.4.2/src/os_test.h new file mode 100644 index 0000000..dc0a04a --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_test.h @@ -0,0 +1,40 @@ +/* +** 2004 May 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. +** +****************************************************************************** +** +*/ +#ifndef _SQLITE_OS_TEST_H_ +#define _SQLITE_OS_TEST_H_ + +#define OsFile OsRealFile +#define OS_UNIX 1 +#include "os_unix.h" +#undef OS_UNIX +#undef OsFile +#undef SET_FULLSYNC + +/* Include sqliteInt.h now to get the type u8. */ +#include "sqliteInt.h" + +typedef struct OsTestFile* OsFile; +typedef struct OsTestFile OsTestFile; +struct OsTestFile { + u8 **apBlk; /* Array of blocks that have been written to. */ + int nBlk; /* Size of apBlock. */ + int nMaxWrite; /* Largest offset written to. */ + char *zName; /* File name */ + OsRealFile fd; + OsTestFile *pNext; +}; + +void sqlite3SetCrashParams(int iDelay, char const *zFile); + +#endif /* _SQLITE_OS_UNIX_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_unix.c b/client/src/thirdparty/sqlite-3.4.2/src/os_unix.c new file mode 100644 index 0000000..6f9b3c0 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_unix.c @@ -0,0 +1,2758 @@ +/* +** 2004 May 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 that is specific to Unix systems. +*/ +#include "sqliteInt.h" +#if OS_UNIX /* This file is used on unix only */ + +/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */ + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, these should be no-ops. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** standard include files. +*/ +#include +#include +#include +#include +#include +#include +#include +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#include +#include +#include +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. +*/ +#if SQLITE_THREADSAFE +# include +# define SQLITE_UNIX_THREADS 1 +#endif + +/* +** Default permissions when creating a new file +*/ +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 +#endif + +/* +** Maximum supported path-length. +*/ +#define MAX_PATHNAME 512 + + +/* +** The unixFile structure is subclass of sqlite3_file specific for the unix +** protability layer. +*/ +typedef struct unixFile unixFile; +struct unixFile { + sqlite3_io_methods const *pMethod; /* Always the first entry */ +#ifdef SQLITE_TEST + /* In test mode, increase the size of this structure a bit so that + ** it is larger than the struct CrashFile defined in test6.c. + */ + char aPadding[32]; +#endif + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ +#ifdef SQLITE_ENABLE_LOCKING_STYLE + void *lockingContext; /* Locking style specific state */ +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + int dirfd; /* File descriptor for the directory */ +#if SQLITE_THREADSAFE + pthread_t tid; /* The thread that "owns" this unixFile */ +#endif +}; + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Define various macros that are missing from some systems. +*/ +#ifndef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifdef SQLITE_DISABLE_LFS +# undef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/* +** The DJGPP compiler environment looks mostly like Unix, but it +** lacks the fcntl() system call. So redefine fcntl() to be something +** that always succeeds. This means that locking does not occur under +** DJGPP. But it is DOS - what did you expect? +*/ +#ifdef __DJGPP__ +# define fcntl(A,B,C) 0 +#endif + +/* +** The threadid macro resolves to the thread-id or to 0. Used for +** testing and debugging only. +*/ +#if SQLITE_THREADSAFE +#define threadid pthread_self() +#else +#define threadid 0 +#endif + +/* +** Set or check the unixFile.tid field. This field is set when an unixFile +** is first opened. All subsequent uses of the unixFile verify that the +** same thread is operating on the unixFile. Some operating systems do +** not allow locks to be overridden by other threads and that restriction +** means that sqlite3* database handles cannot be moved from one thread +** to another. This logic makes sure a user does not try to do that +** by mistake. +** +** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the unixFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information +*/ +#if SQLITE_THREADSAFE +# define SET_THREADID(X) (X)->tid = pthread_self() +# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ + !pthread_equal((X)->tid, pthread_self())) +#else +# define SET_THREADID(X) +# define CHECK_THREADID(X) 0 +#endif + +/* +** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) +** section 6.5.2.2 lines 483 through 490 specify that when a process +** sets or clears a lock, that operation overrides any prior locks set +** by the same process. It does not explicitly say so, but this implies +** that it overrides locks set by the same process using a different +** file descriptor. Consider this test case: +** +** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); +** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); +** +** Suppose ./file1 and ./file2 are really the same file (because +** one is a hard or symbolic link to the other) then if you set +** an exclusive lock on fd1, then try to get an exclusive lock +** on fd2, it works. I would have expected the second lock to +** fail since there was already a lock on the file due to fd1. +** But not so. Since both locks came from the same process, the +** second overrides the first, even though they were on different +** file descriptors opened on different file names. +** +** Bummer. If you ask me, this is broken. Badly broken. It means +** that we cannot use POSIX locks to synchronize file access among +** competing threads of the same process. POSIX locks will work fine +** to synchronize access for threads in separate processes, but not +** threads within the same process. +** +** To work around the problem, SQLite has to manage file locks internally +** on its own. Whenever a new database is opened, we have to find the +** specific inode of the database file (the inode is determined by the +** st_dev and st_ino fields of the stat structure that fstat() fills in) +** and check for locks already existing on that inode. When locks are +** created or removed, we have to look at our own internal record of the +** locks to see if another thread has previously set a lock on that same +** inode. +** +** The sqlite3_file structure for POSIX is no longer just an integer file +** descriptor. It is now a structure that holds the integer file +** descriptor and a pointer to a structure that describes the internal +** locks on the corresponding inode. There is one locking structure +** per inode, so if the same inode is opened twice, both unixFile structures +** point to the same locking structure. The locking structure keeps +** a reference count (so we will know when to delete it) and a "cnt" +** field that tells us its internal lock status. cnt==0 means the +** file is unlocked. cnt==-1 means the file has an exclusive lock. +** cnt>0 means there are cnt shared locks on the file. +** +** Any attempt to lock or unlock a file first checks the locking +** structure. The fcntl() system call is only invoked to set a +** POSIX lock if the internal lock structure transitions between +** a locked and an unlocked state. +** +** 2004-Jan-11: +** More recent discoveries about POSIX advisory locks. (The more +** I discover, the more I realize the a POSIX advisory locks are +** an abomination.) +** +** If you close a file descriptor that points to a file that has locks, +** all locks on that file that are owned by the current process are +** released. To work around this problem, each unixFile structure contains +** a pointer to an openCnt structure. There is one openCnt structure +** per open inode, which means that multiple unixFile can point to a single +** openCnt. When an attempt is made to close an unixFile, if there are +** other unixFile open on the same inode that are holding locks, the call +** to close() the file descriptor is deferred until all of the locks clear. +** The openCnt structure keeps a list of file descriptors that need to +** be closed and that list is walked (and cleared) when the last lock +** clears. +** +** First, under Linux threads, because each thread has a separate +** process ID, lock operations in one thread do not override locks +** to the same file in other threads. Linux threads behave like +** separate processes in this respect. But, if you close a file +** descriptor in linux threads, all locks are cleared, even locks +** on other threads and even though the other threads have different +** process IDs. Linux threads is inconsistent in this respect. +** (I'm beginning to think that linux threads is an abomination too.) +** The consequence of this all is that the hash table for the lockInfo +** structure has to include the process id as part of its key because +** locks in different threads are treated as distinct. But the +** openCnt structure should not include the process id in its +** key because close() clears lock on all threads, not just the current +** thread. Were it not for this goofiness in linux threads, we could +** combine the lockInfo and openCnt structures into a single structure. +** +** 2004-Jun-28: +** On some versions of linux, threads can override each others locks. +** On others not. Sometimes you can change the behavior on the same +** system by setting the LD_ASSUME_KERNEL environment variable. The +** POSIX standard is silent as to which behavior is correct, as far +** as I can tell, so other versions of unix might show the same +** inconsistency. There is no little doubt in my mind that posix +** advisory locks and linux threads are profoundly broken. +** +** To work around the inconsistencies, we have to test at runtime +** whether or not threads can override each others locks. This test +** is run once, the first time any lock is attempted. A static +** variable is set to record the results of this test for future +** use. +*/ + +/* +** An instance of the following structure serves as the key used +** to locate a particular lockInfo structure given its inode. +** +** If threads cannot override each others locks, then we set the +** lockKey.tid field to the thread ID. If threads can override +** each others locks then tid is always set to zero. tid is omitted +** if we compile without threading support. +*/ +struct lockKey { + dev_t dev; /* Device number */ + ino_t ino; /* Inode number */ +#if SQLITE_THREADSAFE + pthread_t tid; /* Thread ID or zero if threads can override each other */ +#endif +}; + +/* +** An instance of the following structure is allocated for each open +** inode on each thread with a different process ID. (Threads have +** different process IDs on linux, but not on most other unixes.) +** +** A single inode can have multiple file descriptors, so each unixFile +** structure contains a pointer to an instance of this object and this +** object keeps a count of the number of unixFile pointing to it. +*/ +struct lockInfo { + struct lockKey key; /* The lookup key */ + int cnt; /* Number of SHARED locks held */ + int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + int nRef; /* Number of pointers to this structure */ +}; + +/* +** An instance of the following structure serves as the key used +** to locate a particular openCnt structure given its inode. This +** is the same as the lockKey except that the thread ID is omitted. +*/ +struct openKey { + dev_t dev; /* Device number */ + ino_t ino; /* Inode number */ +}; + +/* +** An instance of the following structure is allocated for each open +** inode. This structure keeps track of the number of locks on that +** inode. If a close is attempted against an inode that is holding +** locks, the close is deferred until all locks clear by adding the +** file descriptor to be closed to the pending list. +*/ +struct openCnt { + struct openKey key; /* The lookup key */ + int nRef; /* Number of pointers to this structure */ + int nLock; /* Number of outstanding locks */ + int nPending; /* Number of pending close() operations */ + int *aPending; /* Malloced space holding fd's awaiting a close() */ +}; + +/* +** These hash tables map inodes and file descriptors (really, lockKey and +** openKey structures) into lockInfo and openCnt structures. Access to +** these hash tables must be protected by a mutex. +*/ +static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0}; +static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0}; + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** The locking styles are associated with the different file locking +** capabilities supported by different file systems. +** +** POSIX locking style fully supports shared and exclusive byte-range locks +** ADP locking only supports exclusive byte-range locks +** FLOCK only supports a single file-global exclusive lock +** DOTLOCK isn't a true locking style, it refers to the use of a special +** file named the same as the database file with a '.lock' extension, this +** can be used on file systems that do not offer any reliable file locking +** NO locking means that no locking will be attempted, this is only used for +** read-only file systems currently +** UNSUPPORTED means that no locking will be attempted, this is only used for +** file systems that are known to be unsupported +*/ +typedef enum { + posixLockingStyle = 0, /* standard posix-advisory locks */ + afpLockingStyle, /* use afp locks */ + flockLockingStyle, /* use flock() */ + dotlockLockingStyle, /* use .lock files */ + noLockingStyle, /* useful for read-only file system */ + unsupportedLockingStyle /* indicates unsupported file system */ +} sqlite3LockingStyle; +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Helper functions to obtain and relinquish the global mutex. +*/ +static void enterMutex(){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); +} +static void leaveMutex(){ + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); +} + +#if SQLITE_THREADSAFE +/* +** This variable records whether or not threads can override each others +** locks. +** +** 0: No. Threads cannot override each others locks. +** 1: Yes. Threads can override each others locks. +** -1: We don't know yet. +** +** On some systems, we know at compile-time if threads can override each +** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro +** will be set appropriately. On other systems, we have to check at +** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is +** undefined. +** +** This variable normally has file scope only. But during testing, we make +** it a global so that the test code can change its value in order to verify +** that the right stuff happens in either case. +*/ +#ifndef SQLITE_THREAD_OVERRIDE_LOCK +# define SQLITE_THREAD_OVERRIDE_LOCK -1 +#endif +#ifdef SQLITE_TEST +int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#else +static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#endif + +/* +** This structure holds information passed into individual test +** threads by the testThreadLockingBehavior() routine. +*/ +struct threadTestData { + int fd; /* File to be locked */ + struct flock lock; /* The locking operation */ + int result; /* Result of the locking operation */ +}; + +#ifdef SQLITE_LOCK_TRACE +/* +** Print out information about all locking operations. +** +** This routine is used for troubleshooting locks on multithreaded +** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE +** command-line option on the compiler. This code is normally +** turned off. +*/ +static int lockTrace(int fd, int op, struct flock *p){ + char *zOpName, *zType; + int s; + int savedErrno; + if( op==F_GETLK ){ + zOpName = "GETLK"; + }else if( op==F_SETLK ){ + zOpName = "SETLK"; + }else{ + s = fcntl(fd, op, p); + sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); + return s; + } + if( p->l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( p->l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( p->l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + assert( p->l_whence==SEEK_SET ); + s = fcntl(fd, op, p); + savedErrno = errno; + sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", + threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, + (int)p->l_pid, s); + if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ + struct flock l2; + l2 = *p; + fcntl(fd, F_GETLK, &l2); + if( l2.l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( l2.l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( l2.l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", + zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); + } + errno = savedErrno; + return s; +} +#define fcntl lockTrace +#endif /* SQLITE_LOCK_TRACE */ + +/* +** The testThreadLockingBehavior() routine launches two separate +** threads on this routine. This routine attempts to lock a file +** descriptor then returns. The success or failure of that attempt +** allows the testThreadLockingBehavior() procedure to determine +** whether or not threads can override each others locks. +*/ +static void *threadLockingTest(void *pArg){ + struct threadTestData *pData = (struct threadTestData*)pArg; + pData->result = fcntl(pData->fd, F_SETLK, &pData->lock); + return pArg; +} + +/* +** This procedure attempts to determine whether or not threads +** can override each others locks then sets the +** threadsOverrideEachOthersLocks variable appropriately. +*/ +static void testThreadLockingBehavior(int fd_orig){ + int fd; + struct threadTestData d[2]; + pthread_t t[2]; + + fd = dup(fd_orig); + if( fd<0 ) return; + memset(d, 0, sizeof(d)); + d[0].fd = fd; + d[0].lock.l_type = F_RDLCK; + d[0].lock.l_len = 1; + d[0].lock.l_start = 0; + d[0].lock.l_whence = SEEK_SET; + d[1] = d[0]; + d[1].lock.l_type = F_WRLCK; + pthread_create(&t[0], 0, threadLockingTest, &d[0]); + pthread_create(&t[1], 0, threadLockingTest, &d[1]); + pthread_join(t[0], 0); + pthread_join(t[1], 0); + close(fd); + threadsOverrideEachOthersLocks = d[0].result==0 && d[1].result==0; +} +#endif /* SQLITE_THREADSAFE */ + +/* +** Release a lockInfo structure previously allocated by findLockInfo(). +*/ +static void releaseLockInfo(struct lockInfo *pLock){ + if (pLock == NULL) + return; + pLock->nRef--; + if( pLock->nRef==0 ){ + sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); + sqlite3_free(pLock); + } +} + +/* +** Release a openCnt structure previously allocated by findLockInfo(). +*/ +static void releaseOpenCnt(struct openCnt *pOpen){ + if (pOpen == NULL) + return; + pOpen->nRef--; + if( pOpen->nRef==0 ){ + sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); + free(pOpen->aPending); + sqlite3_free(pOpen); + } +} + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** Tests a byte-range locking query to see if byte range locks are +** supported, if not we fall back to dotlockLockingStyle. +*/ +static sqlite3LockingStyle sqlite3TestLockingStyle( + const char *filePath, + int fd +){ + /* test byte-range lock using fcntl */ + struct flock lockInfo; + + lockInfo.l_len = 1; + lockInfo.l_start = 0; + lockInfo.l_whence = SEEK_SET; + lockInfo.l_type = F_RDLCK; + + if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) { + return posixLockingStyle; + } + + /* testing for flock can give false positives. So if if the above test + ** fails, then we fall back to using dot-lock style locking. + */ + return dotlockLockingStyle; +} + +/* +** Examines the f_fstypename entry in the statfs structure as returned by +** stat() for the file system hosting the database file, assigns the +** appropriate locking style based on its value. These values and +** assignments are based on Darwin/OSX behavior and have not been tested on +** other systems. +*/ +static sqlite3LockingStyle sqlite3DetectLockingStyle( + const char *filePath, + int fd +){ + +#ifdef SQLITE_FIXED_LOCKING_STYLE + return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE; +#else + struct statfs fsInfo; + + if (statfs(filePath, &fsInfo) == -1) + return sqlite3TestLockingStyle(filePath, fd); + + if (fsInfo.f_flags & MNT_RDONLY) + return noLockingStyle; + + if( (!strcmp(fsInfo.f_fstypename, "hfs")) || + (!strcmp(fsInfo.f_fstypename, "ufs")) ) + return posixLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "afpfs")) + return afpLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "nfs")) + return sqlite3TestLockingStyle(filePath, fd); + + if(!strcmp(fsInfo.f_fstypename, "smbfs")) + return flockLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "msdos")) + return dotlockLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "webdav")) + return unsupportedLockingStyle; + + return sqlite3TestLockingStyle(filePath, fd); +#endif /* SQLITE_FIXED_LOCKING_STYLE */ +} + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Given a file descriptor, locate lockInfo and openCnt structures that +** describes that file descriptor. Create new ones if necessary. The +** return values might be uninitialized if an error occurs. +** +** Return the number of errors. +*/ +static int findLockInfo( + int fd, /* The file descriptor used in the key */ + struct lockInfo **ppLock, /* Return the lockInfo structure here */ + struct openCnt **ppOpen /* Return the openCnt structure here */ +){ + int rc; + struct lockKey key1; + struct openKey key2; + struct stat statbuf; + struct lockInfo *pLock; + struct openCnt *pOpen; + rc = fstat(fd, &statbuf); + if( rc!=0 ) return 1; + + memset(&key1, 0, sizeof(key1)); + key1.dev = statbuf.st_dev; + key1.ino = statbuf.st_ino; +#if SQLITE_THREADSAFE + if( threadsOverrideEachOthersLocks<0 ){ + testThreadLockingBehavior(fd); + } + key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); +#endif + memset(&key2, 0, sizeof(key2)); + key2.dev = statbuf.st_dev; + key2.ino = statbuf.st_ino; + pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); + if( pLock==0 ){ + struct lockInfo *pOld; + pLock = sqlite3_malloc( sizeof(*pLock) ); + if( pLock==0 ){ + rc = 1; + goto exit_findlockinfo; + } + pLock->key = key1; + pLock->nRef = 1; + pLock->cnt = 0; + pLock->locktype = 0; + pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); + if( pOld!=0 ){ + assert( pOld==pLock ); + sqlite3_free(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pLock->nRef++; + } + *ppLock = pLock; + if( ppOpen!=0 ){ + pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); + if( pOpen==0 ){ + struct openCnt *pOld; + pOpen = sqlite3_malloc( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + pOpen->key = key2; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); + if( pOld!=0 ){ + assert( pOld==pOpen ); + sqlite3_free(pOpen); + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pOpen->nRef++; + } + *ppOpen = pOpen; + } + +exit_findlockinfo: + return rc; +} + +#ifdef SQLITE_DEBUG +/* +** Helper function for printing out trace information from debugging +** binaries. This returns the string represetation of the supplied +** integer lock-type. +*/ +static const char *locktypeName(int locktype){ + switch( locktype ){ + case NO_LOCK: return "NONE"; + case SHARED_LOCK: return "SHARED"; + case RESERVED_LOCK: return "RESERVED"; + case PENDING_LOCK: return "PENDING"; + case EXCLUSIVE_LOCK: return "EXCLUSIVE"; + } + return "ERROR"; +} +#endif + +/* +** If we are currently in a different thread than the thread that the +** unixFile argument belongs to, then transfer ownership of the unixFile +** over to the current thread. +** +** A unixFile is only owned by a thread on systems where one thread is +** unable to override locks created by a different thread. RedHat9 is +** an example of such a system. +** +** Ownership transfer is only allowed if the unixFile is currently unlocked. +** If the unixFile is locked and an ownership is wrong, then return +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. +*/ +#if SQLITE_THREADSAFE +static int transferOwnership(unixFile *pFile){ + int rc; + pthread_t hSelf; + if( threadsOverrideEachOthersLocks ){ + /* Ownership transfers not needed on this system */ + return SQLITE_OK; + } + hSelf = pthread_self(); + if( pthread_equal(pFile->tid, hSelf) ){ + /* We are still in the same thread */ + OSTRACE1("No-transfer, same thread\n"); + return SQLITE_OK; + } + if( pFile->locktype!=NO_LOCK ){ + /* We cannot change ownership while we are holding a lock! */ + return SQLITE_MISUSE; + } + OSTRACE4("Transfer ownership of %d from %d to %d\n", + pFile->h, pFile->tid, hSelf); + pFile->tid = hSelf; + if (pFile->pLock != NULL) { + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile->h, &pFile->pLock, 0); + OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; + } else { + return SQLITE_OK; + } +} +#else + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK +#endif + +/* +** Seek to the offset passed as the second argument, then read cnt +** bytes into pBuf. Return the number of bytes actually read. +** +** NB: If you define USE_PREAD or USE_PREAD64, then it might also +** be necessary to define _XOPEN_SOURCE to be 500. This varies from +** one system to another. Since SQLite does not define USE_PREAD +** any any form by default, we will not attempt to define _XOPEN_SOURCE. +** See tickets #2741 and #2681. +*/ +static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ + int got; + i64 newOffset; + TIMER_START; +#if defined(USE_PREAD) + got = pread(id->h, pBuf, cnt, offset); + SimulateIOError( got = -1 ); +#elif defined(USE_PREAD64) + got = pread64(id->h, pBuf, cnt, offset); + SimulateIOError( got = -1 ); +#else + newOffset = lseek(id->h, offset, SEEK_SET); + SimulateIOError( newOffset-- ); + if( newOffset!=offset ){ + return -1; + } + got = read(id->h, pBuf, cnt); +#endif + TIMER_END; + OSTRACE5("READ %-3d %5d %7lld %d\n", id->h, got, offset, TIMER_ELAPSED); + return got; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int unixRead( + sqlite3_file *id, + void *pBuf, + int amt, + sqlite3_int64 offset +){ + int got; + assert( id ); + got = seekAndRead((unixFile*)id, offset, pBuf, amt); + if( got==amt ){ + return SQLITE_OK; + }else if( got<0 ){ + return SQLITE_IOERR_READ; + }else{ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +*/ +static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){ + int got; + i64 newOffset; + TIMER_START; +#if defined(USE_PREAD) + got = pwrite(id->h, pBuf, cnt, offset); +#elif defined(USE_PREAD64) + got = pwrite64(id->h, pBuf, cnt, offset); +#else + newOffset = lseek(id->h, offset, SEEK_SET); + if( newOffset!=offset ){ + return -1; + } + got = write(id->h, pBuf, cnt); +#endif + TIMER_END; + OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, offset, TIMER_ELAPSED); + return got; +} + + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int unixWrite( + sqlite3_file *id, + const void *pBuf, + int amt, + sqlite3_int64 offset +){ + int wrote = 0; + assert( id ); + assert( amt>0 ); + while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){ + amt -= wrote; + offset += wrote; + pBuf = &((char*)pBuf)[wrote]; + } + SimulateIOError(( wrote=(-1), amt=1 )); + SimulateDiskfullError(( wrote=0, amt=1 )); + if( amt>0 ){ + if( wrote<0 ){ + return SQLITE_IOERR_WRITE; + }else{ + return SQLITE_FULL; + } + } + return SQLITE_OK; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +int sqlite3_sync_count = 0; +int sqlite3_fullsync_count = 0; +#endif + +/* +** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined. +** Otherwise use fsync() in its place. +*/ +#ifndef HAVE_FDATASYNC +# define fdatasync fsync +#endif + +/* +** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not +** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently +** only available on Mac OS X. But that could change. +*/ +#ifdef F_FULLFSYNC +# define HAVE_FULLFSYNC 1 +#else +# define HAVE_FULLFSYNC 0 +#endif + + +/* +** The fsync() system call does not work as advertised on many +** unix systems. The following procedure is an attempt to make +** it work better. +** +** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful +** for testing when we want to run through the test suite quickly. +** You are strongly advised *not* to deploy with SQLITE_NO_SYNC +** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash +** or power failure will likely corrupt the database file. +*/ +static int full_fsync(int fd, int fullSync, int dataOnly){ + int rc; + + /* Record the number of times that we do a normal fsync() and + ** FULLSYNC. This is used during testing to verify that this procedure + ** gets called with the correct arguments. + */ +#ifdef SQLITE_TEST + if( fullSync ) sqlite3_fullsync_count++; + sqlite3_sync_count++; +#endif + + /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a + ** no-op + */ +#ifdef SQLITE_NO_SYNC + rc = SQLITE_OK; +#else + +#if HAVE_FULLFSYNC + if( fullSync ){ + rc = fcntl(fd, F_FULLFSYNC, 0); + }else{ + rc = 1; + } + /* If the FULLFSYNC failed, fall back to attempting an fsync(). + * It shouldn't be possible for fullfsync to fail on the local + * file system (on OSX), so failure indicates that FULLFSYNC + * isn't supported for this file system. So, attempt an fsync + * and (for now) ignore the overhead of a superfluous fcntl call. + * It'd be better to detect fullfsync support once and avoid + * the fcntl call every time sync is called. + */ + if( rc ) rc = fsync(fd); + +#else + if( dataOnly ){ + rc = fdatasync(fd); + }else{ + rc = fsync(fd); + } +#endif /* HAVE_FULLFSYNC */ +#endif /* defined(SQLITE_NO_SYNC) */ + + return rc; +} + +/* +** Make sure all writes to a particular file are committed to disk. +** +** If dataOnly==0 then both the file itself and its metadata (file +** size, access time, etc) are synced. If dataOnly!=0 then only the +** file data is synced. +** +** Under Unix, also make sure that the directory entry for the file +** has been created by fsync-ing the directory that contains the file. +** If we do not do this and we encounter a power failure, the directory +** entry for the journal might not exist after we reboot. The next +** SQLite to access the file will not know that the journal exists (because +** the directory entry for the journal was never created) and the transaction +** will not roll back - possibly leading to database corruption. +*/ +static int unixSync(sqlite3_file *id, int flags){ + int rc; + unixFile *pFile = (unixFile*)id; + + int isDataOnly = (flags&SQLITE_SYNC_DATAONLY); + int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL; + + /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ + assert((flags&0x0F)==SQLITE_SYNC_NORMAL + || (flags&0x0F)==SQLITE_SYNC_FULL + ); + + assert( pFile ); + OSTRACE2("SYNC %-3d\n", pFile->h); + rc = full_fsync(pFile->h, isFullsync, isDataOnly); + SimulateIOError( rc=1 ); + if( rc ){ + return SQLITE_IOERR_FSYNC; + } + if( pFile->dirfd>=0 ){ + OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + HAVE_FULLFSYNC, isFullsync); +#ifndef SQLITE_DISABLE_DIRSYNC + /* The directory sync is only attempted if full_fsync is + ** turned off or unavailable. If a full_fsync occurred above, + ** then the directory sync is superfluous. + */ + if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){ + /* + ** We have received multiple reports of fsync() returning + ** errors when applied to directories on certain file systems. + ** A failed directory sync is not a big deal. So it seems + ** better to ignore the error. Ticket #1657 + */ + /* return SQLITE_IOERR; */ + } +#endif + close(pFile->dirfd); /* Only need to sync once, so close the directory */ + pFile->dirfd = -1; /* when we are done. */ + } + return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +static int unixTruncate(sqlite3_file *id, i64 nByte){ + int rc; + assert( id ); + SimulateIOError( return SQLITE_IOERR_TRUNCATE ); + rc = ftruncate(((unixFile*)id)->h, (off_t)nByte); + if( rc ){ + return SQLITE_IOERR_TRUNCATE; + }else{ + return SQLITE_OK; + } +} + +/* +** Determine the current size of a file in bytes +*/ +static int unixFileSize(sqlite3_file *id, i64 *pSize){ + int rc; + struct stat buf; + assert( id ); + rc = fstat(((unixFile*)id)->h, &buf); + SimulateIOError( rc=1 ); + if( rc!=0 ){ + return SQLITE_IOERR_FSTAT; + } + *pSize = buf.st_size; + return SQLITE_OK; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero. If the file is unlocked or holds only SHARED locks, then +** return zero. +*/ +static int unixCheckReservedLock(sqlite3_file *id){ + int r = 0; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + enterMutex(); /* Because pFile->pLock is shared across threads */ + + /* Check if a thread in this process holds such a lock */ + if( pFile->pLock->locktype>SHARED_LOCK ){ + r = 1; + } + + /* Otherwise see if some other process holds it. + */ + if( !r ){ + struct flock lock; + lock.l_whence = SEEK_SET; + lock.l_start = RESERVED_BYTE; + lock.l_len = 1; + lock.l_type = F_WRLCK; + fcntl(pFile->h, F_GETLK, &lock); + if( lock.l_type!=F_UNLCK ){ + r = 1; + } + } + + leaveMutex(); + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + + return r; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int unixLock(sqlite3_file *id, int locktype){ + /* The following describes the implementation of the various locks and + ** lock transitions in terms of the POSIX advisory shared and exclusive + ** lock primitives (called read-locks and write-locks below, to avoid + ** confusion with SQLite lock names). The algorithms are complicated + ** slightly in order to be compatible with windows systems simultaneously + ** accessing the same database file, in case that is ever required. + ** + ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved + ** byte', each single bytes at well known offsets, and the 'shared byte + ** range', a range of 510 bytes at a well known offset. + ** + ** To obtain a SHARED lock, a read-lock is obtained on the 'pending + ** byte'. If this is successful, a random byte from the 'shared byte + ** range' is read-locked and the lock on the 'pending byte' released. + ** + ** A process may only obtain a RESERVED lock after it has a SHARED lock. + ** A RESERVED lock is implemented by grabbing a write-lock on the + ** 'reserved byte'. + ** + ** A process may only obtain a PENDING lock after it has obtained a + ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock + ** on the 'pending byte'. This ensures that no new SHARED locks can be + ** obtained, but existing SHARED locks are allowed to persist. A process + ** does not have to obtain a RESERVED lock on the way to a PENDING lock. + ** This property is used by the algorithm for rolling back a journal file + ** after a crash. + ** + ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is + ** implemented by obtaining a write-lock on the entire 'shared byte + ** range'. Since all other locks require a read-lock on one of the bytes + ** within this range, this ensures that no other locks are held on the + ** database. + ** + ** The reason a single byte cannot be used instead of the 'shared byte + ** range' is that some versions of windows do not support read-locks. By + ** locking a random byte from a range, concurrent SHARED locks may exist + ** even if the locking primitive used is always a write-lock. + */ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + struct lockInfo *pLock = pFile->pLock; + struct flock lock; + int s; + + assert( pFile ); + OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), + locktypeName(pLock->locktype), pLock->cnt , getpid()); + + /* 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 + ** enterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* This mutex is needed because pFile->pLock is shared across threads + */ + enterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + leaveMutex(); + return rc; + } + pLock = pFile->pLock; + + /* If some thread using this PID has a lock via a different unixFile* + ** handle that precludes the requested lock, return BUSY. + */ + if( (pFile->locktype!=pLock->locktype && + (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) + ){ + rc = SQLITE_BUSY; + goto end_lock; + } + + /* If a SHARED lock is requested, and some thread using this PID already + ** has a SHARED or RESERVED lock, then increment reference counts and + ** return SQLITE_OK. + */ + if( locktype==SHARED_LOCK && + (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ + assert( locktype==SHARED_LOCK ); + assert( pFile->locktype==0 ); + assert( pLock->cnt>0 ); + pFile->locktype = SHARED_LOCK; + pLock->cnt++; + pFile->pOpen->nLock++; + goto end_lock; + } + + lock.l_len = 1L; + + lock.l_whence = SEEK_SET; + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( locktype==SHARED_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktypeh, F_SETLK, &lock); + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + goto end_lock; + } + } + + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( locktype==SHARED_LOCK ){ + assert( pLock->cnt==0 ); + assert( pLock->locktype==0 ); + + /* Now get the read-lock */ + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + s = fcntl(pFile->h, F_SETLK, &lock); + + /* Drop the temporary PENDING lock */ + lock.l_start = PENDING_BYTE; + lock.l_len = 1L; + lock.l_type = F_UNLCK; + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + goto end_lock; + } + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + }else{ + pFile->locktype = SHARED_LOCK; + pFile->pOpen->nLock++; + pLock->cnt = 1; + } + }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ + /* We are trying for an exclusive lock but another thread in this + ** same process is still holding a shared lock. */ + rc = SQLITE_BUSY; + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + assert( 0!=pFile->locktype ); + lock.l_type = F_WRLCK; + switch( locktype ){ + case RESERVED_LOCK: + lock.l_start = RESERVED_BYTE; + break; + case EXCLUSIVE_LOCK: + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + break; + default: + assert(0); + } + s = fcntl(pFile->h, F_SETLK, &lock); + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + } + } + + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + pLock->locktype = locktype; + }else if( locktype==EXCLUSIVE_LOCK ){ + pFile->locktype = PENDING_LOCK; + pLock->locktype = PENDING_LOCK; + } + +end_lock: + leaveMutex(); + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + rc==SQLITE_OK ? "ok" : "failed"); + return rc; +} + +/* +** Lower the locking level on file descriptor pFile to locktype. locktype +** must be either NO_LOCK or SHARED_LOCK. +** +** 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 unixUnlock(sqlite3_file *id, int locktype){ + struct lockInfo *pLock; + struct flock lock; + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); + + assert( locktype<=SHARED_LOCK ); + if( pFile->locktype<=locktype ){ + return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } + enterMutex(); + pLock = pFile->pLock; + assert( pLock->cnt!=0 ); + if( pFile->locktype>SHARED_LOCK ){ + assert( pLock->locktype==pFile->locktype ); + if( locktype==SHARED_LOCK ){ + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){ + /* This should never happen */ + rc = SQLITE_IOERR_RDLOCK; + } + } + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = PENDING_BYTE; + lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); + if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){ + pLock->locktype = SHARED_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if( locktype==NO_LOCK ){ + struct openCnt *pOpen; + + /* Decrement the shared lock counter. Release the lock using an + ** OS call only when all threads in this same process have released + ** the lock. + */ + pLock->cnt--; + if( pLock->cnt==0 ){ + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = lock.l_len = 0L; + if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){ + pLock->locktype = NO_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + + /* Decrement the count of locks against this same file. When the + ** count reaches zero, close any other file descriptors whose close + ** was deferred because of outstanding locks. + */ + pOpen = pFile->pOpen; + pOpen->nLock--; + assert( pOpen->nLock>=0 ); + if( pOpen->nLock==0 && pOpen->nPending>0 ){ + int i; + for(i=0; inPending; i++){ + close(pOpen->aPending[i]); + } + free(pOpen->aPending); + pOpen->nPending = 0; + pOpen->aPending = 0; + } + } + leaveMutex(); + pFile->locktype = locktype; + return rc; +} + +/* +** Close a file. +*/ +static int unixClose(sqlite3_file *id){ + unixFile *pFile = (unixFile *)id; + if( !pFile ) return SQLITE_OK; + unixUnlock(id, NO_LOCK); + if( pFile->dirfd>=0 ) close(pFile->dirfd); + pFile->dirfd = -1; + enterMutex(); + + if( pFile->pOpen->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pOpen->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + int *aNew; + struct openCnt *pOpen = pFile->pOpen; + aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); + if( aNew==0 ){ + /* If a malloc fails, just leak the file descriptor */ + }else{ + pOpen->aPending = aNew; + pOpen->aPending[pOpen->nPending] = pFile->h; + pOpen->nPending++; + } + }else{ + /* There are no outstanding locks so we can close the file immediately */ + close(pFile->h); + } + releaseLockInfo(pFile->pLock); + releaseOpenCnt(pFile->pOpen); + + leaveMutex(); + OSTRACE2("CLOSE %-3d\n", pFile->h); + OpenCounter(-1); + memset(pFile, 0, sizeof(unixFile)); + return SQLITE_OK; +} + + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#pragma mark AFP Support + +/* + ** The afpLockingContext structure contains all afp lock specific state + */ +typedef struct afpLockingContext afpLockingContext; +struct afpLockingContext { + unsigned long long sharedLockByte; + char *filePath; +}; + +struct ByteRangeLockPB2 +{ + unsigned long long offset; /* offset to first byte to lock */ + unsigned long long length; /* nbr of bytes to lock */ + unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ + unsigned char unLockFlag; /* 1 = unlock, 0 = lock */ + unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */ + int fd; /* file desc to assoc this lock with */ +}; + +#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) + +/* +** Return 0 on success, 1 on failure. To match the behavior of the +** normal posix file locking (used in unixLock for example), we should +** provide 'richer' return codes - specifically to differentiate between +** 'file busy' and 'file system error' results. +*/ +static int _AFPFSSetLock( + const char *path, + int fd, + unsigned long long offset, + unsigned long long length, + int setLockFlag +){ + struct ByteRangeLockPB2 pb; + int err; + + pb.unLockFlag = setLockFlag ? 0 : 1; + pb.startEndFlag = 0; + pb.offset = offset; + pb.length = length; + pb.fd = fd; + OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n", + (setLockFlag?"ON":"OFF"), fd, offset, length); + err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); + if ( err==-1 ) { + OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno, + strerror(errno)); + return 1; /* error */ + } else { + return 0; + } +} + +/* + ** This routine checks if there is a RESERVED lock held on the specified + ** file by this or any other process. If such a lock is held, return + ** non-zero. If the file is unlocked or holds only SHARED locks, then + ** return zero. + */ +static int afpUnixCheckReservedLock(sqlite3_file *id){ + int r = 0; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + /* Check if a thread in this process holds such a lock */ + if( pFile->locktype>SHARED_LOCK ){ + r = 1; + } + + /* Otherwise see if some other process holds it. + */ + if ( !r ) { + /* lock the byte */ + int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1); + if (failed) { + /* if we failed to get the lock then someone else must have it */ + r = 1; + } else { + /* if we succeeded in taking the reserved lock, unlock it to restore + ** the original state */ + _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0); + } + } + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + + return r; +} + +/* AFP-style locking following the behavior of unixLock, see the unixLock +** function comments for details of lock management. */ +static int afpUnixLock(sqlite3_file *id, int locktype) +{ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + int gotPendingLock = 0; + + assert( pFile ); + OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), getpid()); + /* 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 + ** enterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* This mutex is needed because pFile->pLock is shared across threads + */ + enterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + leaveMutex(); + return rc; + } + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( locktype==SHARED_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktypefilePath, pFile->h, + PENDING_BYTE, 1, 1); + if (failed) { + rc = SQLITE_BUSY; + goto afp_end_lock; + } + } + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( locktype==SHARED_LOCK ){ + int lk, failed; + int tries = 0; + + /* Now get the read-lock */ + /* note that the quality of the randomness doesn't matter that much */ + lk = random(); + context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + failed = _AFPFSSetLock(context->filePath, pFile->h, + SHARED_FIRST+context->sharedLockByte, 1, 1); + + /* Drop the temporary PENDING lock */ + if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) { + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + goto afp_end_lock; + } + + if( failed ){ + rc = SQLITE_BUSY; + } else { + pFile->locktype = SHARED_LOCK; + } + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + int failed = 0; + assert( 0!=pFile->locktype ); + if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { + /* Acquire a RESERVED lock */ + failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1); + } + if (!failed && locktype == EXCLUSIVE_LOCK) { + /* Acquire an EXCLUSIVE lock */ + + /* Remove the shared lock before trying the range. we'll need to + ** reestablish the shared lock if we can't get the afpUnixUnlock + */ + if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST + + context->sharedLockByte, 1, 0)) { + /* now attemmpt to get the exclusive lock range */ + failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, + SHARED_SIZE, 1); + if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST + + context->sharedLockByte, 1, 1)) { + rc = SQLITE_IOERR_RDLOCK; /* this should never happen */ + } + } else { + /* */ + rc = SQLITE_IOERR_UNLOCK; /* this should never happen */ + } + } + if( failed && rc == SQLITE_OK){ + rc = SQLITE_BUSY; + } + } + + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + }else if( locktype==EXCLUSIVE_LOCK ){ + pFile->locktype = PENDING_LOCK; + } + +afp_end_lock: + leaveMutex(); + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + rc==SQLITE_OK ? "ok" : "failed"); + return rc; +} + +/* + ** Lower the locking level on file descriptor pFile to locktype. locktype + ** must be either NO_LOCK or SHARED_LOCK. + ** + ** 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 afpUnixUnlock(sqlite3_file *id, int locktype) { + struct flock lock; + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + assert( pFile ); + OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, + pFile->locktype, getpid()); + + assert( locktype<=SHARED_LOCK ); + if( pFile->locktype<=locktype ){ + return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } + enterMutex(); + if( pFile->locktype>SHARED_LOCK ){ + if( locktype==SHARED_LOCK ){ + int failed = 0; + + /* unlock the exclusive range - then re-establish the shared lock */ + if (pFile->locktype==EXCLUSIVE_LOCK) { + failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, + SHARED_SIZE, 0); + if (!failed) { + /* successfully removed the exclusive lock */ + if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+ + context->sharedLockByte, 1, 1)) { + /* failed to re-establish our shared lock */ + rc = SQLITE_IOERR_RDLOCK; /* This should never happen */ + } + } else { + /* This should never happen - failed to unlock the exclusive range */ + rc = SQLITE_IOERR_UNLOCK; + } + } + } + if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) { + if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){ + /* failed to release the pending lock */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) { + if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) { + /* failed to release the reserved lock */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + } + if( locktype==NO_LOCK ){ + int failed = _AFPFSSetLock(context->filePath, pFile->h, + SHARED_FIRST + context->sharedLockByte, 1, 0); + if (failed) { + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if (rc == SQLITE_OK) + pFile->locktype = locktype; + leaveMutex(); + return rc; +} + +/* + ** Close a file & cleanup AFP specific locking context + */ +static int afpUnixClose(sqlite3_file *id) { + unixFile *pFile = (unixFile*)pId; + + if( !pFile ) return SQLITE_OK; + afpUnixUnlock(*pId, NO_LOCK); + /* free the AFP locking structure */ + if (pFile->lockingContext != NULL) { + if (((afpLockingContext *)pFile->lockingContext)->filePath != NULL) + sqlite3_free(((afpLockingContext*)pFile->lockingContext)->filePath); + sqlite3_free(pFile->lockingContext); + } + + if( pFile->dirfd>=0 ) close(pFile->dirfd); + pFile->dirfd = -1; + close(pFile->h); + OSTRACE2("CLOSE %-3d\n", pFile->h); + OpenCounter(-1); + return SQLITE_OK; +} + + +#pragma mark flock() style locking + +/* + ** The flockLockingContext is not used + */ +typedef void flockLockingContext; + +static int flockUnixCheckReservedLock(sqlite3_file *id) { + unixFile *pFile = (unixFile*)id; + + if (pFile->locktype == RESERVED_LOCK) { + return 1; /* already have a reserved lock */ + } else { + /* attempt to get the lock */ + int rc = flock(pFile->h, LOCK_EX | LOCK_NB); + if (!rc) { + /* got the lock, unlock it */ + flock(pFile->h, LOCK_UN); + return 0; /* no one has it reserved */ + } + return 1; /* someone else might have it reserved */ + } +} + +static int flockUnixLock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->locktype > NO_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* grab an exclusive lock */ + int rc = flock(pFile->h, LOCK_EX | LOCK_NB); + if (rc) { + /* didn't get, must be busy */ + return SQLITE_BUSY; + } else { + /* got it, set the type and return ok */ + pFile->locktype = locktype; + return SQLITE_OK; + } +} + +static int flockUnixUnlock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + + assert( locktype<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->locktype==locktype ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (locktype==SHARED_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* no, really, unlock. */ + int rc = flock(pFile->h, LOCK_UN); + if (rc) + return SQLITE_IOERR_UNLOCK; + else { + pFile->locktype = NO_LOCK; + return SQLITE_OK; + } +} + +/* + ** Close a file. + */ +static int flockUnixClose(sqlite3_file *pId) { + unixFile *pFile = (unixFile*)*pId; + + if( !pFile ) return SQLITE_OK; + flockUnixUnlock(*pId, NO_LOCK); + + if( pFile->dirfd>=0 ) close(pFile->dirfd); + pFile->dirfd = -1; + enterMutex(); + + close(pFile->h); + leaveMutex(); + OSTRACE2("CLOSE %-3d\n", pFile->h); + OpenCounter(-1); + return SQLITE_OK; +} + +#pragma mark Old-School .lock file based locking + +/* + ** The dotlockLockingContext structure contains all dotlock (.lock) lock + ** specific state + */ +typedef struct dotlockLockingContext dotlockLockingContext; +struct dotlockLockingContext { + char *lockPath; +}; + + +static int dotlockUnixCheckReservedLock(sqlite3_file *id) { + unixFile *pFile = (unixFile*)id; + dotlockLockingContext *context = + (dotlockLockingContext *) pFile->lockingContext; + + if (pFile->locktype == RESERVED_LOCK) { + return 1; /* already have a reserved lock */ + } else { + struct stat statBuf; + if (lstat(context->lockPath,&statBuf) == 0) + /* file exists, someone else has the lock */ + return 1; + else + /* file does not exist, we could have it if we want it */ + return 0; + } +} + +static int dotlockUnixLock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + dotlockLockingContext *context = + (dotlockLockingContext *) pFile->lockingContext; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->locktype > NO_LOCK) { + pFile->locktype = locktype; + + /* Always update the timestamp on the old file */ + utimes(context->lockPath,NULL); + return SQLITE_OK; + } + + /* check to see if lock file already exists */ + struct stat statBuf; + if (lstat(context->lockPath,&statBuf) == 0){ + return SQLITE_BUSY; /* it does, busy */ + } + + /* grab an exclusive lock */ + int fd = open(context->lockPath,O_RDONLY|O_CREAT|O_EXCL,0600); + if (fd < 0) { + /* failed to open/create the file, someone else may have stolen the lock */ + return SQLITE_BUSY; + } + close(fd); + + /* got it, set the type and return ok */ + pFile->locktype = locktype; + return SQLITE_OK; +} + +static int dotlockUnixUnlock(sqlite3_file *id, int locktype) { + unixFile *pFile = (unixFile*)id; + dotlockLockingContext *context = + (dotlockLockingContext *) pFile->lockingContext; + + assert( locktype<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->locktype==locktype ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (locktype==SHARED_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* no, really, unlock. */ + unlink(context->lockPath); + pFile->locktype = NO_LOCK; + return SQLITE_OK; +} + +/* + ** Close a file. + */ +static int dotlockUnixClose(sqlite3_file *id) { + unixFile *pFile = (unixFile*)id; + + if( !pFile ) return SQLITE_OK; + dotlockUnixUnlock(*pId, NO_LOCK); + /* free the dotlock locking structure */ + if (pFile->lockingContext != NULL) { + if (((dotlockLockingContext *)pFile->lockingContext)->lockPath != NULL) + sqlite3_free( ( (dotlockLockingContext *) + pFile->lockingContext)->lockPath); + sqlite3_free(pFile->lockingContext); + } + + if( pFile->dirfd>=0 ) close(pFile->dirfd); + pFile->dirfd = -1; + enterMutex(); + + close(pFile->h); + + leaveMutex(); + OSTRACE2("CLOSE %-3d\n", pFile->h); + OpenCounter(-1); + return SQLITE_OK; +} + + +#pragma mark No locking + +/* + ** The nolockLockingContext is void + */ +typedef void nolockLockingContext; + +static int nolockUnixCheckReservedLock(sqlite3_file *id) { + return 0; +} + +static int nolockUnixLock(sqlite3_file *id, int locktype) { + return SQLITE_OK; +} + +static int nolockUnixUnlock(sqlite3_file *id, int locktype) { + return SQLITE_OK; +} + +/* + ** Close a file. + */ +static int nolockUnixClose(sqlite3_file *id) { + unixFile *pFile = (unixFile*)id; + + if( !pFile ) return SQLITE_OK; + if( pFile->dirfd>=0 ) close(pFile->dirfd); + pFile->dirfd = -1; + enterMutex(); + + close(pFile->h); + + leaveMutex(); + OSTRACE2("CLOSE %-3d\n", pFile->h); + OpenCounter(-1); + return SQLITE_OK; +} + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + + +/* +** Information and control of an open file handle. +*/ +static int unixFileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = ((unixFile*)id)->locktype; + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int unixSectorSize(sqlite3_file *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return the device characteristics for the file. This is always 0. +*/ +static int unixDeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +/* +** This vector defines all the methods that can operate on an sqlite3_file +** for unix. +*/ +static const sqlite3_io_methods sqlite3UnixIoMethod = { + 1, /* iVersion */ + unixClose, + unixRead, + unixWrite, + unixTruncate, + unixSync, + unixFileSize, + unixLock, + unixUnlock, + unixCheckReservedLock, + unixFileControl, + unixSectorSize, + unixDeviceCharacteristics +}; + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** This vector defines all the methods that can operate on an sqlite3_file +** for unix with AFP style file locking. +*/ +static const sqlite3_io_methods sqlite3AFPLockingUnixIoMethod = { + 1, /* iVersion */ + unixClose, + unixRead, + unixWrite, + unixTruncate, + unixSync, + unixFileSize, + afpUnixLock, + afpUnixUnlock, + afpUnixCheckReservedLock, + unixFileControl, + unixSectorSize, + unixDeviceCharacteristics +}; + +/* +** This vector defines all the methods that can operate on an sqlite3_file +** for unix with flock() style file locking. +*/ +static const sqlite3_io_methods sqlite3FlockLockingUnixIoMethod = { + 1, /* iVersion */ + flockUnixClose, + unixRead, + unixWrite, + unixTruncate, + unixSync, + unixFileSize, + flockUnixLock, + flockUnixUnlock, + flockUnixCheckReservedLock, + unixFileControl, + unixSectorSize, + unixDeviceCharacteristics +}; + +/* +** This vector defines all the methods that can operate on an sqlite3_file +** for unix with dotlock style file locking. +*/ +static const sqlite3_io_methods sqlite3DotlockLockingUnixIoMethod = { + 1, /* iVersion */ + dotlockUnixClose, + unixRead, + unixWrite, + unixTruncate, + unixSync, + unixFileSize, + dotlockUnixLock, + dotlockUnixUnlock, + dotlockUnixCheckReservedLock, + unixFileControl, + unixSectorSize, + unixDeviceCharacteristics +}; + +/* +** This vector defines all the methods that can operate on an sqlite3_file +** for unix with dotlock style file locking. +*/ +static const sqlite3_io_methods sqlite3NolockLockingUnixIoMethod = { + 1, /* iVersion */ + nolockUnixClose, + unixRead, + unixWrite, + unixTruncate, + unixSync, + unixFileSize, + nolockUnixLock, + nolockUnixUnlock, + nolockUnixCheckReservedLock, + unixFileControl, + unixSectorSize, + unixDeviceCharacteristics +}; + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Allocate memory for a new unixFile and initialize that unixFile. +** Write a pointer to the new unixFile into *pId. +** If we run out of memory, close the file and return an error. +*/ +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** When locking extensions are enabled, the filepath and locking style +** are needed to determine the unixFile pMethod to use for locking operations. +** The locking-style specific lockingContext data structure is created +** and assigned here also. +*/ +static int fillInUnixFile( + int h, /* Open file descriptor of file being opened */ + int dirfd, /* Directory file descriptor */ + sqlite3_file *pId, /* Write completed initialization here */ + const char *zFilename, /* Name of the file being opened */ +){ + sqlite3LockingStyle lockingStyle; + unixFile *pNew = (unixFile *)pId; + int rc; + + memset(pNew, 0, sizeof(unixFile)); + lockingStyle = sqlite3DetectLockingStyle(zFilename, h); + if ( lockingStyle == posixLockingStyle ) { + enterMutex(); + rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); + leaveMutex(); + if( rc ){ + close(h); + unlink(zFilename); + return SQLITE_NOMEM; + } + } else { + /* pLock and pOpen are only used for posix advisory locking */ + pNew->pLock = NULL; + pNew->pOpen = NULL; + } + pNew->dirfd = -1; + pNew->h = h; + SET_THREADID(pNew); + pNew = sqlite3_malloc( sizeof(unixFile) ); + if( pNew==0 ){ + close(h); + enterMutex(); + releaseLockInfo(pNew->pLock); + releaseOpenCnt(pNew->pOpen); + leaveMutex(); + return SQLITE_NOMEM; + }else{ + switch(lockingStyle) { + case afpLockingStyle: { + /* afp locking uses the file path so it needs to be included in + ** the afpLockingContext */ + int nFilename; + pNew->pMethod = &sqlite3AFPLockingUnixIoMethod; + pNew->lockingContext = + sqlite3_malloc(sizeof(afpLockingContext)); + nFilename = strlen(zFilename)+1; + ((afpLockingContext *)pNew->lockingContext)->filePath = + sqlite3_malloc(nFilename); + memcpy(((afpLockingContext *)pNew->lockingContext)->filePath, + zFilename, nFilename); + srandomdev(); + break; + } + case flockLockingStyle: + /* flock locking doesn't need additional lockingContext information */ + pNew->pMethod = &sqlite3FlockLockingUnixIoMethod; + break; + case dotlockLockingStyle: { + /* dotlock locking uses the file path so it needs to be included in + ** the dotlockLockingContext */ + int nFilename; + pNew->pMethod = &sqlite3DotlockLockingUnixIoMethod; + pNew->lockingContext = sqlite3_malloc( + sizeof(dotlockLockingContext)); + nFilename = strlen(zFilename) + 6; + ((dotlockLockingContext *)pNew->lockingContext)->lockPath = + sqlite3_malloc( nFilename ); + sqlite3_snprintf(nFilename, + ((dotlockLockingContext *)pNew->lockingContext)->lockPath, + "%s.lock", zFilename); + break; + } + case posixLockingStyle: + /* posix locking doesn't need additional lockingContext information */ + pNew->pMethod = &sqlite3UnixIoMethod; + break; + case noLockingStyle: + case unsupportedLockingStyle: + default: + pNew->pMethod = &sqlite3NolockLockingUnixIoMethod; + } + OpenCounter(+1); + return SQLITE_OK; + } +} +#else /* SQLITE_ENABLE_LOCKING_STYLE */ +static int fillInUnixFile( + int h, /* Open file descriptor on file being opened */ + int dirfd, + sqlite3_file *pId, /* Write to the unixFile structure here */ + const char *zFilename /* Name of the file being opened */ +){ + unixFile *pNew = (unixFile *)pId; + int rc; + +#ifdef FD_CLOEXEC + fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); +#endif + + enterMutex(); + rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen); + leaveMutex(); + if( rc ){ + if( dirfd>=0 ) close(dirfd); + close(h); + return SQLITE_NOMEM; + } + + OSTRACE3("OPEN %-3d %s\n", h, zFilename); + pNew->dirfd = -1; + pNew->h = h; + pNew->dirfd = dirfd; + SET_THREADID(pNew); + + pNew->pMethod = &sqlite3UnixIoMethod; + OpenCounter(+1); + return SQLITE_OK; +} +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Open a file descriptor to the directory containing file zFilename. +** If successful, *pFd is set to the opened file descriptor and +** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM +** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined +** value. +** +** If SQLITE_OK is returned, the caller is responsible for closing +** the file descriptor *pFd using close(). +*/ +static int openDirectory(const char *zFilename, int *pFd){ + int ii; + int fd = -1; + char zDirname[MAX_PATHNAME+1]; + + sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename); + for(ii=strlen(zDirname); ii>=0 && zDirname[ii]!='/'; ii--); + if( ii>0 ){ + zDirname[ii] = '\0'; + fd = open(zDirname, O_RDONLY|O_BINARY, 0); + if( fd>=0 ){ +#ifdef FD_CLOEXEC + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname); + } + } + *pFd = fd; + return (fd>=0?SQLITE_OK:SQLITE_CANTOPEN); +} + +/* +** Open the file zPath. +** +** Previously, the SQLite OS layer used three functions in place of this +** one: +** +** sqlite3OsOpenReadWrite(); +** sqlite3OsOpenReadOnly(); +** sqlite3OsOpenExclusive(); +** +** These calls correspond to the following combinations of flags: +** +** ReadWrite() -> (READWRITE | CREATE) +** ReadOnly() -> (READONLY) +** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE) +** +** The old OpenExclusive() accepted a boolean argument - "delFlag". If +** true, the file was configured to be automatically deleted when the +** file handle closed. To achieve the same effect using this new +** interface, add the DELETEONCLOSE flag to those specified above for +** OpenExclusive(). +*/ +static int unixOpen( + sqlite3_vfs *pVfs, + const char *zPath, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + int fd = 0; /* File descriptor returned by open() */ + int dirfd = -1; /* Directory file descriptor */ + int oflags = 0; /* Flags to pass to open() */ + int eType = flags&0xFFFFFF00; /* Type of file to open */ + + int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); + int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); + int isCreate = (flags & SQLITE_OPEN_CREATE); + int isReadonly = (flags & SQLITE_OPEN_READONLY); + int isReadWrite = (flags & SQLITE_OPEN_READWRITE); + + /* If creating a master or main-file journal, this function will open + ** a file-descriptor on the directory too. The first time unixSync() + ** is called the directory file descriptor will be fsync()ed and close()d. + */ + int isOpenDirectory = (isCreate && + (eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL) + ); + + /* Check the following statements are true: + ** + ** (a) Exactly one of the READWRITE and READONLY flags must be set, and + ** (b) if CREATE is set, then READWRITE must also be set, and + ** (c) if EXCLUSIVE is set, then CREATE must also be set. + ** (d) if DELETEONCLOSE is set, then CREATE must also be set. + */ + assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); + assert(isCreate==0 || isReadWrite); + assert(isExclusive==0 || isCreate); + assert(isDelete==0 || isCreate); + + + /* The main DB, main journal, and master journal are never automatically + ** deleted + */ + assert( eType!=SQLITE_OPEN_MAIN_DB || !isDelete ); + assert( eType!=SQLITE_OPEN_MAIN_JOURNAL || !isDelete ); + assert( eType!=SQLITE_OPEN_MASTER_JOURNAL || !isDelete ); + + /* Assert that the upper layer has set one of the "file-type" flags. */ + assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB + || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL + || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL + || eType==SQLITE_OPEN_TRANSIENT_DB + ); + + if( isReadonly ) oflags |= O_RDONLY; + if( isReadWrite ) oflags |= O_RDWR; + if( isCreate ) oflags |= O_CREAT; + if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW); + oflags |= (O_LARGEFILE|O_BINARY); + + memset(pFile, 0, sizeof(unixFile)); + fd = open(zPath, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); + if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ + /* Failed to open the file for read/write access. Try read-only. */ + flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); + flags |= SQLITE_OPEN_READONLY; + return unixOpen(pVfs, zPath, pFile, flags, pOutFlags); + } + if( fd<0 ){ + return SQLITE_CANTOPEN; + } + if( isDelete ){ + unlink(zPath); + } + if( pOutFlags ){ + *pOutFlags = flags; + } + + assert(fd!=0); + if( isOpenDirectory ){ + int rc = openDirectory(zPath, &dirfd); + if( rc!=SQLITE_OK ){ + close(fd); + return rc; + } + } + return fillInUnixFile(fd, dirfd, pFile, zPath); +} + +/* +** Delete the file at zPath. If the dirSync argument is true, fsync() +** the directory after deleting the file. +*/ +static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + int rc = SQLITE_OK; + SimulateIOError(return SQLITE_IOERR_DELETE); + unlink(zPath); + if( dirSync ){ + int fd; + rc = openDirectory(zPath, &fd); + if( rc==SQLITE_OK ){ + if( fsync(fd) ){ + rc = SQLITE_IOERR_DIR_FSYNC; + } + close(fd); + } + } + return rc; +} + +/* +** Test the existance of or access permissions of file zPath. The +** test performed depends on the value of flags: +** +** SQLITE_ACCESS_EXISTS: Return 1 if the file exists +** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable. +** SQLITE_ACCESS_READONLY: Return 1 if the file is readable. +** +** Otherwise return 0. +*/ +static int unixAccess(sqlite3_vfs *pVfs, const char *zPath, int flags){ + int amode = 0; + switch( flags ){ + case SQLITE_ACCESS_EXISTS: + amode = F_OK; + break; + case SQLITE_ACCESS_READWRITE: + amode = W_OK|R_OK; + break; + case SQLITE_ACCESS_READ: + amode = R_OK; + break; + + default: + assert(!"Invalid flags argument"); + } + return (access(zPath, amode)==0); +} + +/* +** Create a temporary file name in zBuf. zBuf must be allocated +** by the calling process and must be big enough to hold at least +** pVfs->mxPathname bytes. +*/ +static int unixGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + static const char *azDirs[] = { + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + }; + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + struct stat buf; + const char *zDir = "."; + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. + */ + SimulateIOError( return SQLITE_ERROR ); + + azDirs[0] = sqlite3_temp_directory; + for(i=0; imxPathname==MAX_PATHNAME ); + sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir); + j = strlen(zBuf); + sqlite3Randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + }while( access(zBuf,0)==0 ); + return SQLITE_OK; +} + + +/* +** Turn a relative pathname into a full pathname. The relative path +** is stored as a nul-terminated string in the buffer pointed to by +** zPath. +** +** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes +** (in this case, MAX_PATHNAME bytes). The full-path is written to +** this buffer before returning. +*/ +static int unixFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zPath, /* Possibly relative input path */ + int nOut, /* Size of output buffer in bytes */ + char *zOut /* Output buffer */ +){ + + /* It's odd to simulate an io-error here, but really this is just + ** using the io-error infrastructure to test that SQLite handles this + ** function failing. This function could fail if, for example, the + ** current working directly has been unlinked. + */ + SimulateIOError( return SQLITE_ERROR ); + + assert( pVfs->mxPathname==MAX_PATHNAME ); + zOut[nOut-1] = '\0'; + if( zPath[0]=='/' ){ + sqlite3_snprintf(nOut, zOut, "%s", zPath); + }else{ + int nCwd; + if( getcwd(zOut, nOut-1)==0 ){ + return SQLITE_CANTOPEN; + } + nCwd = strlen(zOut); + sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath); + } + return SQLITE_OK; + +#if 0 + /* + ** Remove "/./" path elements and convert "/A/./" path elements + ** to just "/". + */ + if( zFull ){ + int i, j; + for(i=j=0; zFull[i]; i++){ + if( zFull[i]=='/' ){ + if( zFull[i+1]=='/' ) continue; + if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ + i += 1; + continue; + } + if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ + while( j>0 && zFull[j-1]!='/' ){ j--; } + i += 3; + continue; + } + } + zFull[j++] = zFull[i]; + } + zFull[j] = 0; + } +#endif +} + + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +#include +static void *unixDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); +} + +/* +** SQLite calls this function immediately after a call to unixDlSym() or +** unixDlOpen() fails (returns a null pointer). If a more detailed error +** message is available, it is written to zBufOut. If no error message +** is available, zBufOut is left unmodified and SQLite uses a default +** error message. +*/ +static void unixDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ + char *zErr; + enterMutex(); + zErr = dlerror(); + if( zErr ){ + sqlite3_snprintf(nBuf, zBufOut, "%s", zErr); + } + leaveMutex(); +} +static void *unixDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ + return dlsym(pHandle, zSymbol); +} +static void unixDlClose(sqlite3_vfs *pVfs, void *pHandle){ + dlclose(pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define unixDlOpen 0 + #define unixDlError 0 + #define unixDlSym 0 + #define unixDlClose 0 +#endif + +/* +** Write nBuf bytes of random data to the supplied buffer zBuf. +*/ +static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + + assert(nBuf>=(sizeof(time_t)+sizeof(int))); + + /* We have to initialize zBuf to prevent valgrind from reporting + ** errors. The reports issued by valgrind are incorrect - we would + ** prefer that the randomness be increased by making use of the + ** uninitialized space in zBuf - but valgrind errors tend to worry + ** some users. Rather than argue, it seems easier just to initialize + ** the whole array and silence valgrind, even if that means less randomness + ** in the random seed. + ** + ** When testing, initializing zBuf[] to zero is all we do. That means + ** that we always use the same random number sequence. This makes the + ** tests repeatable. + */ + memset(zBuf, 0, nBuf); +#if !defined(SQLITE_TEST) + { + int pid, fd; + fd = open("/dev/urandom", O_RDONLY); + if( fd<0 ){ + time_t t; + time(&t); + memcpy(zBuf, &t, sizeof(t)); + pid = getpid(); + memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid)); + }else{ + read(fd, zBuf, nBuf); + close(fd); + } + } +#endif + return SQLITE_OK; +} + + +/* +** Sleep for a little while. Return the amount of time slept. +** The argument is the number of microseconds we want to sleep. +** The return value is the number of microseconds of sleep actually +** requested from the underlying operating system, a number which +** might be greater than or equal to the argument, but not less +** than the argument. +*/ +static int unixSleep(sqlite3_vfs *pVfs, int microseconds){ +#if defined(HAVE_USLEEP) && HAVE_USLEEP + usleep(microseconds); + return microseconds; +#else + int seconds = (microseconds+999999)/1000000; + sleep(seconds); + return seconds*1000000; +#endif +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +static int unixCurrentTime(sqlite3_vfs *pVfs, double *prNow){ +#ifdef NO_GETTOD + time_t t; + time(&t); + *prNow = t/86400.0 + 2440587.5; +#else + struct timeval sNow; + gettimeofday(&sNow, 0); + *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0; +#endif +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +/* +** Return a pointer to the sqlite3DefaultVfs structure. We use +** a function rather than give the structure global scope because +** some compilers (MSVC) do not allow forward declarations of +** initialized structures. +*/ +sqlite3_vfs *sqlite3OsDefaultVfs(void){ + static sqlite3_vfs unixVfs = { + 1, /* iVersion */ + sizeof(unixFile), /* szOsFile */ + MAX_PATHNAME, /* mxPathname */ + 0, /* pNext */ + "unix", /* zName */ + 0, /* pAppData */ + + unixOpen, /* xOpen */ + unixDelete, /* xDelete */ + unixAccess, /* xAccess */ + unixGetTempname, /* xGetTempName */ + unixFullPathname, /* xFullPathname */ + unixDlOpen, /* xDlOpen */ + unixDlError, /* xDlError */ + unixDlSym, /* xDlSym */ + unixDlClose, /* xDlClose */ + unixRandomness, /* xRandomness */ + unixSleep, /* xSleep */ + unixCurrentTime /* xCurrentTime */ + }; + + return &unixVfs; +} + +#endif /* OS_UNIX */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_unix.h b/client/src/thirdparty/sqlite-3.4.2/src/os_unix.h new file mode 100644 index 0000000..5fdfc2f --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_unix.h @@ -0,0 +1,116 @@ +/* +** 2004 May 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 header file defined OS-specific features for Unix. +*/ +#ifndef _SQLITE_OS_UNIX_H_ +#define _SQLITE_OS_UNIX_H_ + +/* +** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE +** to the compiler command line. +*/ + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** standard include files. +*/ +#include +#include +#include +#include + +/* +** Macros used to determine whether or not to use threads. The +** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for +** Posix threads and SQLITE_W32_THREADS is defined if we are +** synchronizing using Win32 threads. +*/ +#if defined(THREADSAFE) && THREADSAFE +# include +# define SQLITE_UNIX_THREADS 1 +#endif + +/* +** The OsFile structure is a operating-system independing representation +** of an open file handle. It is defined differently for each architecture. +** +** This is the definition for Unix. +** +** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK, +** PENDING_LOCK or EXCLUSIVE_LOCK. +*/ +typedef struct OsFile OsFile; +struct OsFile { + struct Pager *pPager; /* The pager that owns this OsFile. Might be 0 */ + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + unsigned char isOpen; /* True if needs to be closed */ + unsigned char fullSync; /* Use F_FULLSYNC if available */ + int dirfd; /* File descriptor for the directory */ +#ifdef SQLITE_UNIX_THREADS + pthread_t tid; /* The thread authorized to use this OsFile */ +#endif +}; + +/* +** A macro to set the OsFile.fullSync flag, if it exists. +*/ +#define SET_FULLSYNC(x,y) ((x).fullSync = (y)) + +/* +** Maximum number of characters in a temporary file name +*/ +#define SQLITE_TEMPNAME_SIZE 200 + +/* +** Minimum interval supported by sqlite3OsSleep(). +*/ +#if defined(HAVE_USLEEP) && HAVE_USLEEP +# define SQLITE_MIN_SLEEP_MS 1 +#else +# define SQLITE_MIN_SLEEP_MS 1000 +#endif + +/* +** Default permissions when creating a new file +*/ +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 +#endif + + +#endif /* _SQLITE_OS_UNIX_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_win.c b/client/src/thirdparty/sqlite-3.4.2/src/os_win.c new file mode 100644 index 0000000..e5555f1 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_win.c @@ -0,0 +1,1557 @@ +/* +** 2004 May 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 that is specific to windows. +*/ +#include "sqliteInt.h" +#if OS_WIN /* This file is used for windows only */ + + +/* +** A Note About Memory Allocation: +** +** This driver uses malloc()/free() directly rather than going through +** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers +** are designed for use on embedded systems where memory is scarce and +** malloc failures happen frequently. Win32 does not typically run on +** embedded systems, and when it does the developers normally have bigger +** problems to worry about than running out of memory. So there is not +** a compelling need to use the wrappers. +** +** But there is a good reason to not use the wrappers. If we use the +** wrappers then we will get simulated malloc() failures within this +** driver. And that causes all kinds of problems for our tests. We +** could enhance SQLite to deal with simulated malloc failures within +** the OS driver, but the code to deal with those failure would not +** be exercised on Linux (which does not need to malloc() in the driver) +** and so we would have difficulty writing coverage tests for that +** code. Better to leave the code out, we think. +** +** The point of this discussion is as follows: When creating a new +** OS layer for an embedded system, if you use this file as an example, +** avoid the use of malloc()/free(). Those routines work ok on windows +** desktops but not so well in embedded systems. +*/ + +#include + +#ifdef __CYGWIN__ +# include +#endif + +/* +** Macros used to determine whether or not to use threads. +*/ +#if defined(THREADSAFE) && THREADSAFE +# define SQLITE_W32_THREADS 1 +#endif + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define OS_WINCE 1 +# define AreFileApisANSI() 1 +#else +# define OS_WINCE 0 +#endif + +/* +** WinCE lacks native support for file locking so we have to fake it +** with some code of our own. +*/ +#if OS_WINCE +typedef struct winceLock { + int nReaders; /* Number of reader locks obtained */ + BOOL bPending; /* Indicates a pending lock has been obtained */ + BOOL bReserved; /* Indicates a reserved lock has been obtained */ + BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ +} winceLock; +#endif + +/* +** The winFile structure is a subclass of sqlite3_file* specific to the win32 +** portability layer. +*/ +typedef struct winFile winFile; +struct winFile { + const sqlite3_io_methods *pMethod;/* Must be first */ + HANDLE h; /* Handle for accessing the file */ + unsigned char locktype; /* Type of lock currently held on this file */ + short sharedLockByte; /* Randomly chosen byte used as a shared lock */ +#if OS_WINCE + WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ + HANDLE hMutex; /* Mutex used to control access to shared lock */ + HANDLE hShared; /* Shared memory segment used for locking */ + winceLock local; /* Locks obtained by this instance of winFile */ + winceLock *shared; /* Global shared lock memory for the file */ +#endif +}; + + +/* +** The following variable is (normally) set once and never changes +** thereafter. It records whether the operating system is Win95 +** or WinNT. +** +** 0: Operating system unknown. +** 1: Operating system is Win95. +** 2: Operating system is WinNT. +** +** In order to facilitate testing on a WinNT system, the test fixture +** can manually set this value to 1 to emulate Win98 behavior. +*/ +#ifdef SQLITE_TEST +int sqlite3_os_type = 0; +#else +static int sqlite3_os_type = 0; +#endif + +/* +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, +** or WinCE. Return false (zero) for Win95, Win98, or WinME. +** +** Here is an interesting observation: Win95, Win98, and WinME lack +** the LockFileEx() API. But we can still statically link against that +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ +#if OS_WINCE +# define isNT() (1) +#else + static int isNT(void){ + if( sqlite3_os_type==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return sqlite3_os_type==2; + } +#endif /* OS_WINCE */ + +/* +** Convert a UTF-8 string to microsoft unicode (UTF-16?). +** +** Space to hold the returned string is obtained from malloc. +*/ +static WCHAR *utf8ToUnicode(const char *zFilename){ + int nChar; + WCHAR *zWideFilename; + + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) ); + if( zWideFilename==0 ){ + return 0; + } + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); + if( nChar==0 ){ + free(zWideFilename); + zWideFilename = 0; + } + return zWideFilename; +} + +/* +** Convert microsoft unicode to UTF-8. Space to hold the returned string is +** obtained from malloc(). +*/ +static char *unicodeToUtf8(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = malloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + free(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert an ansi string to microsoft unicode, based on the +** current codepage settings for file apis. +** +** Space to hold the returned string is obtained +** from malloc. +*/ +static WCHAR *mbcsToUnicode(const char *zFilename){ + int nByte; + WCHAR *zMbcsFilename; + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); + zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) ); + if( zMbcsFilename==0 ){ + return 0; + } + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); + if( nByte==0 ){ + free(zMbcsFilename); + zMbcsFilename = 0; + } + return zMbcsFilename; +} + +/* +** Convert microsoft unicode to multibyte character string, based on the +** user's Ansi codepage. +** +** Space to hold the returned string is obtained from +** malloc(). +*/ +static char *unicodeToMbcs(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = malloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + free(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert multibyte character string to UTF-8. Space to hold the +** returned string is obtained from malloc(). +*/ +static char *mbcsToUtf8(const char *zFilename){ + char *zFilenameUtf8; + WCHAR *zTmpWide; + + zTmpWide = mbcsToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameUtf8 = unicodeToUtf8(zTmpWide); + free(zTmpWide); + return zFilenameUtf8; +} + +/* +** Convert UTF-8 to multibyte character string. Space to hold the +** returned string is obtained from malloc(). +*/ +static char *utf8ToMbcs(const char *zFilename){ + char *zFilenameMbcs; + WCHAR *zTmpWide; + + zTmpWide = utf8ToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameMbcs = unicodeToMbcs(zTmpWide); + free(zTmpWide); + return zFilenameMbcs; +} + +#if OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ +/* +** WindowsCE does not have a localtime() function. So create a +** substitute. +*/ +#include +struct tm *__cdecl localtime(const time_t *t) +{ + static struct tm y; + FILETIME uTm, lTm; + SYSTEMTIME pTm; + sqlite3_int64 t64; + t64 = *t; + t64 = (t64 + 11644473600)*10000000; + uTm.dwLowDateTime = t64 & 0xFFFFFFFF; + uTm.dwHighDateTime= t64 >> 32; + FileTimeToLocalFileTime(&uTm,&lTm); + FileTimeToSystemTime(&lTm,&pTm); + y.tm_year = pTm.wYear - 1900; + y.tm_mon = pTm.wMonth - 1; + y.tm_wday = pTm.wDayOfWeek; + y.tm_mday = pTm.wDay; + y.tm_hour = pTm.wHour; + y.tm_min = pTm.wMinute; + y.tm_sec = pTm.wSecond; + return &y; +} + +/* This will never be called, but defined to make the code compile */ +#define GetTempPathA(a,b) + +#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) +#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) +#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) + +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)] + +/* +** Acquire a lock on the handle h +*/ +static void winceMutexAcquire(HANDLE h){ + DWORD dwErr; + do { + dwErr = WaitForSingleObject(h, INFINITE); + } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); +} +/* +** Release a lock acquired by winceMutexAcquire() +*/ +#define winceMutexRelease(h) ReleaseMutex(h) + +/* +** Create the mutex and shared memory used for locking in the file +** descriptor pFile +*/ +static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ + WCHAR *zTok; + WCHAR *zName = utf8ToUnicode(zFilename); + BOOL bInit = TRUE; + + /* Initialize the local lockdata */ + ZeroMemory(&pFile->local, sizeof(pFile->local)); + + /* Replace the backslashes from the filename and lowercase it + ** to derive a mutex name. */ + zTok = CharLowerW(zName); + for (;*zTok;zTok++){ + if (*zTok == '\\') *zTok = '_'; + } + + /* Create/open the named mutex */ + pFile->hMutex = CreateMutexW(NULL, FALSE, zName); + if (!pFile->hMutex){ + free(zName); + return FALSE; + } + + /* Acquire the mutex before continuing */ + winceMutexAcquire(pFile->hMutex); + + /* Since the names of named mutexes, semaphores, file mappings etc are + ** case-sensitive, take advantage of that by uppercasing the mutex name + ** and using that as the shared filemapping name. + */ + CharUpperW(zName); + pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(winceLock), + zName); + + /* Set a flag that indicates we're the first to create the memory so it + ** must be zero-initialized */ + if (GetLastError() == ERROR_ALREADY_EXISTS){ + bInit = FALSE; + } + + free(zName); + + /* If we succeeded in making the shared memory handle, map it. */ + if (pFile->hShared){ + pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, + FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); + /* If mapping failed, close the shared memory handle and erase it */ + if (!pFile->shared){ + CloseHandle(pFile->hShared); + pFile->hShared = NULL; + } + } + + /* If shared memory could not be created, then close the mutex and fail */ + if (pFile->hShared == NULL){ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + return FALSE; + } + + /* Initialize the shared memory if we're supposed to */ + if (bInit) { + ZeroMemory(pFile->shared, sizeof(winceLock)); + } + + winceMutexRelease(pFile->hMutex); + return TRUE; +} + +/* +** Destroy the part of winFile that deals with wince locks +*/ +static void winceDestroyLock(winFile *pFile){ + if (pFile->hMutex){ + /* Acquire the mutex */ + winceMutexAcquire(pFile->hMutex); + + /* The following blocks should probably assert in debug mode, but they + are to cleanup in case any locks remained open */ + if (pFile->local.nReaders){ + pFile->shared->nReaders --; + } + if (pFile->local.bReserved){ + pFile->shared->bReserved = FALSE; + } + if (pFile->local.bPending){ + pFile->shared->bPending = FALSE; + } + if (pFile->local.bExclusive){ + pFile->shared->bExclusive = FALSE; + } + + /* De-reference and close our copy of the shared memory handle */ + UnmapViewOfFile(pFile->shared); + CloseHandle(pFile->hShared); + + /* Done with the mutex */ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + } +} + +/* +** An implementation of the LockFile() API of windows for wince +*/ +static BOOL winceLockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Wanting an exclusive lock? */ + if (dwFileOffsetLow == SHARED_FIRST + && nNumberOfBytesToLockLow == SHARED_SIZE){ + if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ + pFile->shared->bExclusive = TRUE; + pFile->local.bExclusive = TRUE; + bReturn = TRUE; + } + } + + /* Want a read-only lock? */ + else if ((dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) && + nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bExclusive == 0){ + pFile->local.nReaders ++; + if (pFile->local.nReaders == 1){ + pFile->shared->nReaders ++; + } + bReturn = TRUE; + } + } + + /* Want a pending lock? */ + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){ + /* If no pending lock has been acquired, then acquire it */ + if (pFile->shared->bPending == 0) { + pFile->shared->bPending = TRUE; + pFile->local.bPending = TRUE; + bReturn = TRUE; + } + } + /* Want a reserved lock? */ + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bReserved == 0) { + pFile->shared->bReserved = TRUE; + pFile->local.bReserved = TRUE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the UnlockFile API of windows for wince +*/ +static BOOL winceUnlockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Releasing a reader lock or an exclusive lock */ + if (dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){ + /* Did we have an exclusive lock? */ + if (pFile->local.bExclusive){ + pFile->local.bExclusive = FALSE; + pFile->shared->bExclusive = FALSE; + bReturn = TRUE; + } + + /* Did we just have a reader lock? */ + else if (pFile->local.nReaders){ + pFile->local.nReaders --; + if (pFile->local.nReaders == 0) + { + pFile->shared->nReaders --; + } + bReturn = TRUE; + } + } + + /* Releasing a pending lock */ + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bPending){ + pFile->local.bPending = FALSE; + pFile->shared->bPending = FALSE; + bReturn = TRUE; + } + } + /* Releasing a reserved lock */ + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bReserved) { + pFile->local.bReserved = FALSE; + pFile->shared->bReserved = FALSE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the LockFileEx() API of windows for wince +*/ +static BOOL winceLockFileEx( + HANDLE *phFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped +){ + /* If the caller wants a shared read lock, forward this call + ** to winceLockFile */ + if (lpOverlapped->Offset == SHARED_FIRST && + dwFlags == 1 && + nNumberOfBytesToLockLow == SHARED_SIZE){ + return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); + } + return FALSE; +} +/* +** End of the special code for wince +*****************************************************************************/ +#endif /* OS_WINCE */ + +/***************************************************************************** +** The next group of routines implement the I/O methods specified +** by the sqlite3_io_methods object. +******************************************************************************/ + +/* +** Close a file. +** +** It is reported that an attempt to close a handle might sometimes +** fail. This is a very unreasonable result, but windows is notorious +** for being unreasonable so I do not doubt that it might happen. If +** the close fails, we pause for 100 milliseconds and try again. As +** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before +** giving up and returning an error. +*/ +#define MX_CLOSE_ATTEMPT 3 +static int winClose(sqlite3_file *id){ + int rc, cnt = 0; + winFile *pFile = (winFile*)id; + OSTRACE2("CLOSE %d\n", pFile->h); + do{ + rc = CloseHandle(pFile->h); + }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); +#if OS_WINCE + winceDestroyLock(pFile); + if( pFile->zDeleteOnClose ){ + DeleteFileW(pFile->zDeleteOnClose); + free(pFile->zDeleteOnClose); + } +#endif + OpenCounter(-1); + return rc ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Some microsoft compilers lack this definition. +*/ +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int winRead( + sqlite3_file *id, /* File to read from */ + void *pBuf, /* Write content into this buffer */ + int amt, /* Number of bytes to read */ + sqlite3_int64 offset /* Begin reading at this offset */ +){ + LONG upperBits = (offset>>32) & 0x7fffffff; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; + DWORD got; + winFile *pFile = (winFile*)id; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_READ); + OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype); + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } + if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){ + return SQLITE_IOERR_READ; + } + if( got==(DWORD)amt ){ + return SQLITE_OK; + }else{ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int winWrite( + sqlite3_file *id, /* File to write into */ + const void *pBuf, /* The bytes to be written */ + int amt, /* Number of bytes to write */ + sqlite3_int64 offset /* Offset into the file to begin writing at */ +){ + LONG upperBits = (offset>>32) & 0x7fffffff; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; + DWORD wrote; + winFile *pFile = (winFile*)id; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_WRITE); + SimulateDiskfullError(return SQLITE_FULL); + OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype); + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } + assert( amt>0 ); + while( + amt>0 + && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 + ){ + amt -= wrote; + pBuf = &((char*)pBuf)[wrote]; + } + if( !rc || amt>(int)wrote ){ + return SQLITE_FULL; + } + return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ + LONG upperBits = (nByte>>32) & 0x7fffffff; + LONG lowerBits = nByte & 0xffffffff; + winFile *pFile = (winFile*)id; + OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); + SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); + SetEndOfFile(pFile->h); + return SQLITE_OK; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +int sqlite3_sync_count = 0; +int sqlite3_fullsync_count = 0; +#endif + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +static int winSync(sqlite3_file *id, int flags){ + winFile *pFile = (winFile*)id; + OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype); +#ifdef SQLITE_TEST + if( flags & SQLITE_SYNC_FULL ){ + sqlite3_fullsync_count++; + } + sqlite3_sync_count++; +#endif + if( FlushFileBuffers(pFile->h) ){ + return SQLITE_OK; + }else{ + return SQLITE_IOERR; + } +} + +/* +** Determine the current size of a file in bytes +*/ +static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ + winFile *pFile = (winFile*)id; + DWORD upperBits, lowerBits; + SimulateIOError(return SQLITE_IOERR_FSTAT); + lowerBits = GetFileSize(pFile->h, &upperBits); + *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; + return SQLITE_OK; +} + +/* +** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. +*/ +#ifndef LOCKFILE_FAIL_IMMEDIATELY +# define LOCKFILE_FAIL_IMMEDIATELY 1 +#endif + +/* +** Acquire a reader lock. +** Different API routines are called depending on whether or not this +** is Win95 or WinNT. +*/ +static int getReadLock(winFile *pFile){ + int res; + if( isNT() ){ + OVERLAPPED ovlp; + ovlp.Offset = SHARED_FIRST; + ovlp.OffsetHigh = 0; + ovlp.hEvent = 0; + res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, + 0, SHARED_SIZE, 0, &ovlp); + }else{ + int lk; + sqlite3Randomness(sizeof(lk), &lk); + pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); + } + return res; +} + +/* +** Undo a readlock +*/ +static int unlockReadLock(winFile *pFile){ + int res; + if( isNT() ){ + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + }else{ + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); + } + return res; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. The winUnlock() routine +** erases all locks at once and returns us immediately to locking level 0. +** It is not possible to lower the locking level one step at a time. You +** must go straight to locking level 0. +*/ +static int winLock(sqlite3_file *id, int locktype){ + int rc = SQLITE_OK; /* Return code from subroutines */ + int res = 1; /* Result of a windows lock call */ + int newLocktype; /* Set pFile->locktype to this value before exiting */ + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; + + assert( pFile!=0 ); + OSTRACE5("LOCK %d %d was %d(%d)\n", + pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); + + /* If there is already a lock of this type or more restrictive on the + ** OsFile, do nothing. Don't use the end_lock: exit path, as + ** sqlite3OsEnterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or + ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of + ** the PENDING_LOCK byte is temporary. + */ + newLocktype = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) + ){ + int cnt = 3; + while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ + /* Try 3 times to get the pending lock. The pending lock might be + ** held by another reader process who will release it momentarily. + */ + OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); + Sleep(1); + } + gotPendingLock = res; + } + + /* Acquire a shared lock + */ + if( locktype==SHARED_LOCK && res ){ + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); + if( res ){ + newLocktype = SHARED_LOCK; + } + } + + /* Acquire a RESERVED lock + */ + if( locktype==RESERVED_LOCK && res ){ + assert( pFile->locktype==SHARED_LOCK ); + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + if( res ){ + newLocktype = RESERVED_LOCK; + } + } + + /* Acquire a PENDING lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + newLocktype = PENDING_LOCK; + gotPendingLock = 0; + } + + /* Acquire an EXCLUSIVE lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); + OSTRACE2("unreadlock = %d\n", res); + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( res ){ + newLocktype = EXCLUSIVE_LOCK; + }else{ + OSTRACE2("error-code = %d\n", GetLastError()); + getReadLock(pFile); + } + } + + /* If we are holding a PENDING lock that ought to be released, then + ** release it now. + */ + if( gotPendingLock && locktype==SHARED_LOCK ){ + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + } + + /* Update the state of the lock has held in the file descriptor then + ** return the appropriate result code. + */ + if( res ){ + rc = SQLITE_OK; + }else{ + OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, + locktype, newLocktype); + rc = SQLITE_BUSY; + } + pFile->locktype = newLocktype; + return rc; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero, otherwise zero. +*/ +static int winCheckReservedLock(sqlite3_file *id){ + int rc; + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ + rc = 1; + OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); + }else{ + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + if( rc ){ + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + } + rc = !rc; + OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); + } + return rc; +} + +/* +** Lower the locking level on file descriptor id to locktype. locktype +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +** +** It is not possible for this routine to fail if the second argument +** is NO_LOCK. If the second argument is SHARED_LOCK then this routine +** might return SQLITE_IOERR; +*/ +static int winUnlock(sqlite3_file *id, int locktype){ + int type; + winFile *pFile = (winFile*)id; + int rc = SQLITE_OK; + assert( pFile!=0 ); + assert( locktype<=SHARED_LOCK ); + OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + pFile->locktype, pFile->sharedLockByte); + type = pFile->locktype; + if( type>=EXCLUSIVE_LOCK ){ + UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ + /* This should never happen. We should always be able to + ** reacquire the read lock */ + rc = SQLITE_IOERR_UNLOCK; + } + } + if( type>=RESERVED_LOCK ){ + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + } + if( locktype==NO_LOCK && type>=SHARED_LOCK ){ + unlockReadLock(pFile); + } + if( type>=PENDING_LOCK ){ + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + } + pFile->locktype = locktype; + return rc; +} + +/* +** Control and query of the open file handle. +*/ +static int winFileControl(sqlite3_file *id, int op, void *pArg){ + switch( op ){ + case SQLITE_FCNTL_LOCKSTATE: { + *(int*)pArg = ((winFile*)id)->locktype; + return SQLITE_OK; + } + } + return SQLITE_ERROR; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and its journal file) that the sector size will be the +** same for both. +*/ +static int winSectorSize(sqlite3_file *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** Return a vector of device characteristics. +*/ +static int winDeviceCharacteristics(sqlite3_file *id){ + return 0; +} + +/* +** This vector defines all the methods that can operate on an +** sqlite3_file for win32. +*/ +static const sqlite3_io_methods winIoMethod = { + 1, /* iVersion */ + winClose, + winRead, + winWrite, + winTruncate, + winSync, + winFileSize, + winLock, + winUnlock, + winCheckReservedLock, + winFileControl, + winSectorSize, + winDeviceCharacteristics +}; + +/*************************************************************************** +** Here ends the I/O methods that form the sqlite3_io_methods object. +** +** The next block of code implements the VFS methods. +****************************************************************************/ + +/* +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from malloc and must be freed by the calling +** function. +*/ +static void *convertUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( isNT() ){ + zConverted = utf8ToUnicode(zFilename); + }else{ + zConverted = utf8ToMbcs(zFilename); + } + /* caller will handle out of memory */ + return zConverted; +} + +/* +** Open a file. +*/ +static int winOpen( + sqlite3_vfs *pVfs, /* Not used */ + const char *zName, /* Name of the file (UTF-8) */ + sqlite3_file *id, /* Write the SQLite file handle here */ + int flags, /* Open mode flags */ + int *pOutFlags /* Status return flags */ +){ + HANDLE h; + DWORD dwDesiredAccess; + DWORD dwShareMode; + DWORD dwCreationDisposition; + DWORD dwFlagsAndAttributes = 0; + int isTemp; + winFile *pFile = (winFile*)id; + void *zConverted = convertUtf8Filename(zName); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + + if( flags & SQLITE_OPEN_READWRITE ){ + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + }else{ + dwDesiredAccess = GENERIC_READ; + } + if( flags & SQLITE_OPEN_CREATE ){ + dwCreationDisposition = OPEN_ALWAYS; + }else{ + dwCreationDisposition = OPEN_EXISTING; + } + if( flags & SQLITE_OPEN_MAIN_DB ){ + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + }else{ + dwShareMode = 0; + } + if( flags & SQLITE_OPEN_DELETEONCLOSE ){ +#if OS_WINCE + dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; +#else + dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY + | FILE_ATTRIBUTE_HIDDEN + | FILE_FLAG_DELETE_ON_CLOSE; +#endif + isTemp = 1; + }else{ + dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; + isTemp = 0; + } + /* Reports from the internet are that performance is always + ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL + ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + h = CreateFileA((char*)zConverted, + dwDesiredAccess, + dwShareMode, + NULL, + dwCreationDisposition, + dwFlagsAndAttributes, + NULL + ); +#endif + } + if( h==INVALID_HANDLE_VALUE ){ + free(zConverted); + if( flags & SQLITE_OPEN_READWRITE ){ + return winOpen(0, zName, id, + ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); + }else{ + return SQLITE_CANTOPEN; + } + } + if( pOutFlags ){ + if( flags & SQLITE_OPEN_READWRITE ){ + *pOutFlags = SQLITE_OPEN_READWRITE; + }else{ + *pOutFlags = SQLITE_OPEN_READONLY; + } + } + memset(pFile, 0, sizeof(*pFile)); + pFile->pMethod = &winIoMethod; + pFile->h = h; +#if OS_WINCE + if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == + (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) + && !winceCreateLock(zName, pFile) + ){ + CloseHandle(h); + free(zConverted); + return SQLITE_CANTOPEN; + } + if( isTemp ){ + pFile->zDeleteOnClose = zConverted; + }else +#endif + { + free(zConverted); + } + OpenCounter(+1); + return SQLITE_OK; +} + +/* +** Delete the named file. +** +** Note that windows does not allow a file to be deleted if some other +** process has it open. Sometimes a virus scanner or indexing program +** will open a journal file shortly after it is created in order to do +** whatever does. While this other process is holding the +** file open, we will be unable to delete it. To work around this +** problem, we delay 100 milliseconds and try to delete again. Up +** to MX_DELETION_ATTEMPTs deletion attempts are run before giving +** up and returning an error. +*/ +#define MX_DELETION_ATTEMPTS 5 +static int winDelete( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to delete */ + int syncDir /* Not used on win32 */ +){ + int cnt = 0; + int rc; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + SimulateIOError(return SQLITE_IOERR_DELETE); + if( isNT() ){ + do{ + DeleteFileW(zConverted); + }while( (rc = GetFileAttributesW(zConverted))!=0xffffffff + && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + do{ + DeleteFileA(zConverted); + }while( (rc = GetFileAttributesA(zConverted))!=0xffffffff + && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); +#endif + } + free(zConverted); + OSTRACE2("DELETE \"%s\"\n", zFilename); + return rc==0xffffffff ? SQLITE_OK : SQLITE_IOERR_DELETE; +} + +/* +** Check the existance and status of a file. +*/ +static int winAccess( + sqlite3_vfs *pVfs, /* Not used on win32 */ + const char *zFilename, /* Name of file to check */ + int flags /* Type of test to make on this file */ +){ + DWORD attr; + int rc; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + if( isNT() ){ + attr = GetFileAttributesW((WCHAR*)zConverted); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + attr = GetFileAttributesA((char*)zConverted); +#endif + } + free(zConverted); + switch( flags ){ + case SQLITE_ACCESS_READ: + case SQLITE_ACCESS_EXISTS: + rc = attr!=0xffffffff; + break; + case SQLITE_ACCESS_READWRITE: + rc = (attr & FILE_ATTRIBUTE_READONLY)==0; + break; + default: + assert(!"Invalid flags argument"); + } + return rc; +} + + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at pVfs->mxPathname characters. +*/ +static int winGetTempname(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + static char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + char zTempPath[MAX_PATH+1]; + if( sqlite3_temp_directory ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); + }else if( isNT() ){ + char *zMulti; + WCHAR zWidePath[MAX_PATH]; + GetTempPathW(MAX_PATH-30, zWidePath); + zMulti = unicodeToUtf8(zWidePath); + if( zMulti ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); + free(zMulti); + }else{ + return SQLITE_NOMEM; + } + }else{ + char *zUtf8; + char zMbcsPath[MAX_PATH]; + GetTempPathA(MAX_PATH-30, zMbcsPath); + zUtf8 = mbcsToUtf8(zMbcsPath); + if( zUtf8 ){ + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); + free(zUtf8); + }else{ + return SQLITE_NOMEM; + } + } + for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} + zTempPath[i] = 0; + sqlite3_snprintf(nBuf-30, zBuf, + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); + j = strlen(zBuf); + sqlite3Randomness(20, &zBuf[j]); + for(i=0; i<20; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + OSTRACE2("TEMP FILENAME: %s\n", zBuf); + return SQLITE_OK; +} + +/* +** Turn a relative pathname into a full pathname. Write the full +** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname +** bytes in size. +*/ +static int winFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + +#if defined(__CYGWIN__) + cygwin_conv_to_full_win32_path(zRelative, zFull); + return SQLITE_OK; +#endif + +#if OS_WINCE + /* WinCE has no concept of a relative pathname, or so I am told. */ + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); + return SQLITE_OK; +#endif + +#if !OS_WINCE && !defined(__CYGWIN__) + int nByte; + void *zConverted; + char *zOut; + zConverted = convertUtf8Filename(zRelative); + if( isNT() ){ + WCHAR *zTemp; + nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; + zTemp = malloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + free(zConverted); + return SQLITE_NOMEM; + } + GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); + free(zConverted); + zOut = unicodeToUtf8(zTemp); + free(zTemp); + }else{ + char *zTemp; + nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; + zTemp = malloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + free(zConverted); + return SQLITE_NOMEM; + } + GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); + free(zConverted); + zOut = mbcsToUtf8(zTemp); + free(zTemp); + } + if( zOut ){ + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); + free(zOut); + return SQLITE_OK; + }else{ + return SQLITE_NOMEM; + } +#endif +} + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ + HANDLE h; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return 0; + } + if( isNT() ){ + h = LoadLibraryW((WCHAR*)zConverted); + }else{ +#if OS_WINCE + return 0; +#else + h = LoadLibraryA((char*)zConverted); +#endif + } + free(zConverted); + return (void*)h; +} +static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ +#if OS_WINCE + int error = GetLastError(); + if( error>0x7FFFFFF ){ + sqlite3_snprintf(nBuf, zBufOut, "OsError 0x%x", error); + }else{ + sqlite3_snprintf(nBuf, zBufOut, "OsError %d", error); + } +#else + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + 0, + zBufOut, + nBuf-1, + 0 + ); +#endif +} +void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ +#if OS_WINCE + /* The GetProcAddressA() routine is only available on wince. */ + return GetProcAddressA((HANDLE)pHandle, zSymbol); +#else + /* All other windows platforms expect GetProcAddress() to take + ** an Ansi string regardless of the _UNICODE setting */ + return GetProcAddress((HANDLE)pHandle, zSymbol); +#endif +} +void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ + FreeLibrary((HANDLE)pHandle); +} +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ + #define winDlOpen 0 + #define winDlError 0 + #define winDlSym 0 + #define winDlClose 0 +#endif + + +/* +** Write up to nBuf bytes of randomness into zBuf. +*/ +static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ + int n = 0; + if( sizeof(SYSTEMTIME)<=nBuf-n ){ + SYSTEMTIME x; + GetSystemTime(&x); + memcpy(&zBuf[n], &x, sizeof(x)); + n += sizeof(x); + } + if( sizeof(DWORD)<=nBuf-n ){ + DWORD pid = GetCurrentProcessId(); + memcpy(&zBuf[n], &pid, sizeof(pid)); + n += sizeof(pid); + } + if( sizeof(DWORD)<=nBuf-n ){ + DWORD cnt = GetTickCount(); + memcpy(&zBuf[n], &cnt, sizeof(cnt)); + n += sizeof(cnt); + } + if( sizeof(LARGE_INTEGER)<=nBuf-n ){ + LARGE_INTEGER i; + QueryPerformanceCounter(&i); + memcpy(&zBuf[n], &i, sizeof(i)); + n += sizeof(i); + } + return n; +} + + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +static int winSleep(sqlite3_vfs *pVfs, int microsec){ + Sleep((microsec+999)/1000); + return ((microsec+999)/1000)*1000; +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ + FILETIME ft; + /* FILETIME structure is a 64-bit value representing the number of + 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). + */ + double now; +#if OS_WINCE + SYSTEMTIME time; + GetSystemTime(&time); + SystemTimeToFileTime(&time,&ft); +#else + GetSystemTimeAsFileTime( &ft ); +#endif + now = ((double)ft.dwHighDateTime) * 4294967296.0; + *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + + +/* +** Return a pointer to the sqlite3DefaultVfs structure. We use +** a function rather than give the structure global scope because +** some compilers (MSVC) do not allow forward declarations of +** initialized structures. +*/ +sqlite3_vfs *sqlite3OsDefaultVfs(void){ + static sqlite3_vfs winVfs = { + 1, /* iVersion */ + sizeof(winFile), /* szOsFile */ + MAX_PATH, /* mxPathname */ + 0, /* pNext */ + "win32", /* zName */ + 0, /* pAppData */ + + winOpen, /* xOpen */ + winDelete, /* xDelete */ + winAccess, /* xAccess */ + winGetTempname, /* xGetTempName */ + winFullPathname, /* xFullPathname */ + winDlOpen, /* xDlOpen */ + winDlError, /* xDlError */ + winDlSym, /* xDlSym */ + winDlClose, /* xDlClose */ + winRandomness, /* xRandomness */ + winSleep, /* xSleep */ + winCurrentTime /* xCurrentTime */ + }; + + return &winVfs; +} + +#endif /* OS_WIN */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/os_win.h b/client/src/thirdparty/sqlite-3.4.2/src/os_win.h new file mode 100644 index 0000000..baf937b --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/os_win.h @@ -0,0 +1,40 @@ +/* +** 2004 May 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 header file defines OS-specific features for Win32 +*/ +#ifndef _SQLITE_OS_WIN_H_ +#define _SQLITE_OS_WIN_H_ + +#include +#include + +/* +** The OsFile structure is a operating-system independing representation +** of an open file handle. It is defined differently for each architecture. +** +** This is the definition for Win32. +*/ +typedef struct OsFile OsFile; +struct OsFile { + HANDLE h; /* Handle for accessing the file */ + unsigned char locktype; /* Type of lock currently held on this file */ + unsigned char isOpen; /* True if needs to be closed */ + short sharedLockByte; /* Randomly chosen byte used as a shared lock */ +}; + + +#define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#define SQLITE_MIN_SLEEP_MS 1 + + +#endif /* _SQLITE_OS_WIN_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/pager.c b/client/src/thirdparty/sqlite-3.4.2/src/pager.c new file mode 100644 index 0000000..5677761 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/pager.c @@ -0,0 +1,5133 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This is the implementation of the page cache subsystem or "pager". +** +** The pager is used to access a database disk file. It implements +** atomic commit and rollback through the use of a journal file that +** is separate from the database file. The pager also implements file +** locking to prevent two processes from writing the same database +** file simultaneously, or one process from reading the database while +** another is writing. +** +** @(#) $Id: pager.c,v 1.405 2008/02/02 20:47:38 drh Exp $ +*/ +#ifndef SQLITE_OMIT_DISKIO +#include "sqliteInt.h" +#include +#include + +/* +** Macros for troubleshooting. Normally turned off +*/ +#if 0 +#define sqlite3DebugPrintf printf +#define PAGERTRACE1(X) sqlite3DebugPrintf(X) +#define PAGERTRACE2(X,Y) sqlite3DebugPrintf(X,Y) +#define PAGERTRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V) +#else +#define PAGERTRACE1(X) +#define PAGERTRACE2(X,Y) +#define PAGERTRACE3(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) +#endif + +/* +** The following two macros are used within the PAGERTRACEX() macros above +** to print out file-descriptors. +** +** PAGERID() takes a pointer to a Pager struct as its argument. The +** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file +** struct as its argument. +*/ +#define PAGERID(p) ((int)(p->fd)) +#define FILEHANDLEID(fd) ((int)fd) + +/* +** The page cache as a whole is always in one of the following +** states: +** +** PAGER_UNLOCK The page cache is not currently reading or +** writing the database file. There is no +** data held in memory. This is the initial +** state. +** +** PAGER_SHARED The page cache is reading the database. +** Writing is not permitted. There can be +** multiple readers accessing the same database +** file at the same time. +** +** PAGER_RESERVED This process has reserved the database for writing +** but has not yet made any changes. Only one process +** at a time can reserve the database. The original +** database file has not been modified so other +** processes may still be reading the on-disk +** database file. +** +** PAGER_EXCLUSIVE The page cache is writing the database. +** Access is exclusive. No other processes or +** threads can be reading or writing while one +** process is writing. +** +** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE +** after all dirty pages have been written to the +** database file and the file has been synced to +** disk. All that remains to do is to remove or +** truncate the journal file and the transaction +** will be committed. +** +** The page cache comes up in PAGER_UNLOCK. The first time a +** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED. +** After all pages have been released using sqlite_page_unref(), +** the state transitions back to PAGER_UNLOCK. The first time +** that sqlite3PagerWrite() is called, the state transitions to +** PAGER_RESERVED. (Note that sqlite3PagerWrite() can only be +** called on an outstanding page which means that the pager must +** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) +** PAGER_RESERVED means that there is an open rollback journal. +** The transition to PAGER_EXCLUSIVE occurs before any changes +** are made to the database file, though writes to the rollback +** journal occurs with just PAGER_RESERVED. After an sqlite3PagerRollback() +** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED, +** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode. +*/ +#define PAGER_UNLOCK 0 +#define PAGER_SHARED 1 /* same as SHARED_LOCK */ +#define PAGER_RESERVED 2 /* same as RESERVED_LOCK */ +#define PAGER_EXCLUSIVE 4 /* same as EXCLUSIVE_LOCK */ +#define PAGER_SYNCED 5 + +/* +** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time, +** then failed attempts to get a reserved lock will invoke the busy callback. +** This is off by default. To see why, consider the following scenario: +** +** Suppose thread A already has a shared lock and wants a reserved lock. +** Thread B already has a reserved lock and wants an exclusive lock. If +** both threads are using their busy callbacks, it might be a long time +** be for one of the threads give up and allows the other to proceed. +** But if the thread trying to get the reserved lock gives up quickly +** (if it never invokes its busy callback) then the contention will be +** resolved quickly. +*/ +#ifndef SQLITE_BUSY_RESERVED_LOCK +# define SQLITE_BUSY_RESERVED_LOCK 0 +#endif + +/* +** This macro rounds values up so that if the value is an address it +** is guaranteed to be an address that is aligned to an 8-byte boundary. +*/ +#define FORCE_ALIGNMENT(X) (((X)+7)&~7) + +typedef struct PgHdr PgHdr; + +/* +** Each pager stores all currently unreferenced pages in a list sorted +** in least-recently-used (LRU) order (i.e. the first item on the list has +** not been referenced in a long time, the last item has been recently +** used). An instance of this structure is included as part of each +** pager structure for this purpose (variable Pager.lru). +** +** Additionally, if memory-management is enabled, all unreferenced pages +** are stored in a global LRU list (global variable sqlite3LruPageList). +** +** In both cases, the PagerLruList.pFirstSynced variable points to +** the first page in the corresponding list that does not require an +** fsync() operation before its memory can be reclaimed. If no such +** page exists, PagerLruList.pFirstSynced is set to NULL. +*/ +typedef struct PagerLruList PagerLruList; +struct PagerLruList { + PgHdr *pFirst; /* First page in LRU list */ + PgHdr *pLast; /* Last page in LRU list (the most recently used) */ + PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0 */ +}; + +/* +** The following structure contains the next and previous pointers used +** to link a PgHdr structure into a PagerLruList linked list. +*/ +typedef struct PagerLruLink PagerLruLink; +struct PagerLruLink { + PgHdr *pNext; + PgHdr *pPrev; +}; + +/* +** Each in-memory image of a page begins with the following header. +** This header is only visible to this pager module. The client +** code that calls pager sees only the data that follows the header. +** +** Client code should call sqlite3PagerWrite() on a page prior to making +** any modifications to that page. The first time sqlite3PagerWrite() +** is called, the original page contents are written into the rollback +** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once +** the journal page has made it onto the disk surface, PgHdr.needSync +** is cleared. The modified page cannot be written back into the original +** database file until the journal pages has been synced to disk and the +** PgHdr.needSync has been cleared. +** +** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and +** is cleared again when the page content is written back to the original +** database file. +** +** Details of important structure elements: +** +** needSync +** +** If this is true, this means that it is not safe to write the page +** content to the database because the original content needed +** for rollback has not by synced to the main rollback journal. +** The original content may have been written to the rollback journal +** but it has not yet been synced. So we cannot write to the database +** file because power failure might cause the page in the journal file +** to never reach the disk. It is as if the write to the journal file +** does not occur until the journal file is synced. +** +** This flag is false if the page content exactly matches what +** currently exists in the database file. The needSync flag is also +** false if the original content has been written to the main rollback +** journal and synced. If the page represents a new page that has +** been added onto the end of the database during the current +** transaction, the needSync flag is true until the original database +** size in the journal header has been synced to disk. +** +** inJournal +** +** This is true if the original page has been written into the main +** rollback journal. This is always false for new pages added to +** the end of the database file during the current transaction. +** And this flag says nothing about whether or not the journal +** has been synced to disk. For pages that are in the original +** database file, the following expression should always be true: +** +** inJournal = (pPager->aInJournal[(pgno-1)/8] & (1<<((pgno-1)%8))!=0 +** +** The pPager->aInJournal[] array is only valid for the original +** pages of the database, not new pages that are added to the end +** of the database, so obviously the above expression cannot be +** valid for new pages. For new pages inJournal is always 0. +** +** dirty +** +** When true, this means that the content of the page has been +** modified and needs to be written back to the database file. +** If false, it means that either the content of the page is +** unchanged or else the content is unimportant and we do not +** care whether or not it is preserved. +** +** alwaysRollback +** +** This means that the sqlite3PagerDontRollback() API should be +** ignored for this page. The DontRollback() API attempts to say +** that the content of the page on disk is unimportant (it is an +** unused page on the freelist) so that it is unnecessary to +** rollback changes to this page because the content of the page +** can change without changing the meaning of the database. This +** flag overrides any DontRollback() attempt. This flag is set +** when a page that originally contained valid data is added to +** the freelist. Later in the same transaction, this page might +** be pulled from the freelist and reused for something different +** and at that point the DontRollback() API will be called because +** pages taken from the freelist do not need to be protected by +** the rollback journal. But this flag says that the page was +** not originally part of the freelist so that it still needs to +** be rolled back in spite of any subsequent DontRollback() calls. +** +** needRead +** +** This flag means (when true) that the content of the page has +** not yet been loaded from disk. The in-memory content is just +** garbage. (Actually, we zero the content, but you should not +** make any assumptions about the content nevertheless.) If the +** content is needed in the future, it should be read from the +** original database file. +*/ +struct PgHdr { + Pager *pPager; /* The pager to which this page belongs */ + Pgno pgno; /* The page number for this page */ + PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ + PagerLruLink free; /* Next and previous free pages */ + PgHdr *pNextAll; /* A list of all pages */ + u8 inJournal; /* TRUE if has been written to journal */ + u8 dirty; /* TRUE if we need to write back changes */ + u8 needSync; /* Sync journal before writing this page */ + u8 alwaysRollback; /* Disable DontRollback() for this page */ + u8 needRead; /* Read content if PagerWrite() is called */ + short int nRef; /* Number of users of this page */ + PgHdr *pDirty, *pPrevDirty; /* Dirty pages */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + PagerLruLink gfree; /* Global list of nRef==0 pages */ +#endif +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; +#endif + void *pData; /* Page data */ + /* Pager.nExtra bytes of local data appended to this header */ +}; + +/* +** For an in-memory only database, some extra information is recorded about +** each page so that changes can be rolled back. (Journal files are not +** used for in-memory databases.) The following information is added to +** the end of every EXTRA block for in-memory databases. +** +** This information could have been added directly to the PgHdr structure. +** But then it would take up an extra 8 bytes of storage on every PgHdr +** even for disk-based databases. Splitting it out saves 8 bytes. This +** is only a savings of 0.8% but those percentages add up. +*/ +typedef struct PgHistory PgHistory; +struct PgHistory { + u8 *pOrig; /* Original page text. Restore to this on a full rollback */ + u8 *pStmt; /* Text as it was at the beginning of the current statement */ + PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */ + u8 inStmt; /* TRUE if in the statement subjournal */ +}; + +/* +** A macro used for invoking the codec if there is one +*/ +#ifdef SQLITE_HAS_CODEC +# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } +# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) +#else +# define CODEC1(P,D,N,X) /* NO-OP */ +# define CODEC2(P,D,N,X) ((char*)D) +#endif + +/* +** Convert a pointer to a PgHdr into a pointer to its data +** and back again. +*/ +#define PGHDR_TO_DATA(P) ((P)->pData) +#define PGHDR_TO_EXTRA(G,P) ((void*)&((G)[1])) +#define PGHDR_TO_HIST(P,PGR) \ + ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->nExtra]) + +/* +** A open page cache is an instance of the following structure. +** +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or +** or SQLITE_FULL. Once one of the first three errors occurs, it persists +** and is returned as the result of every major pager API call. The +** SQLITE_FULL return code is slightly different. It persists only until the +** next successful rollback is performed on the pager cache. Also, +** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup() +** APIs, they may still be used successfully. +*/ +struct Pager { + sqlite3_vfs *pVfs; /* OS functions to use for IO */ + u8 journalOpen; /* True if journal file descriptors is valid */ + u8 journalStarted; /* True if header of journal is synced */ + u8 useJournal; /* Use a rollback journal on this file */ + u8 noReadlock; /* Do not bother to obtain readlocks */ + u8 stmtOpen; /* True if the statement subjournal is open */ + u8 stmtInUse; /* True we are in a statement subtransaction */ + u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ + u8 noSync; /* Do not sync the journal if true */ + u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 sync_flags; /* One of SYNC_NORMAL or SYNC_FULL */ + u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ + u8 tempFile; /* zFilename is a temporary file */ + u8 readOnly; /* True for a read-only database */ + u8 needSync; /* True if an fsync() is needed on the journal */ + u8 dirtyCache; /* True if cached pages have changed */ + u8 alwaysRollback; /* Disable DontRollback() for all pages */ + u8 memDb; /* True to inhibit all file I/O */ + u8 setMaster; /* True if a m-j name has been written to jrnl */ + u8 doNotSync; /* Boolean. While true, do not spill the cache */ + u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ + u8 changeCountDone; /* Set after incrementing the change-counter */ + u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ + int errCode; /* One of several kinds of errors */ + int dbSize; /* Number of pages in the file */ + int origDbSize; /* dbSize before the current change */ + int stmtSize; /* Size of database (in pages) at stmt_begin() */ + int nRec; /* Number of pages written to the journal */ + u32 cksumInit; /* Quasi-random value added to every checksum */ + int stmtNRec; /* Number of records in stmt subjournal */ + int nExtra; /* Add this many bytes to each in-memory page */ + int pageSize; /* Number of bytes in a page */ + int nPage; /* Total number of in-memory pages */ + int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ + int mxPage; /* Maximum number of pages to hold in cache */ + Pgno mxPgno; /* Maximum allowed size of the database */ + u8 *aInJournal; /* One bit for each page in the database file */ + u8 *aInStmt; /* One bit for each page in the database */ + char *zFilename; /* Name of the database file */ + char *zJournal; /* Name of the journal file */ + char *zDirectory; /* Directory hold database and journal files */ + char *zStmtJrnl; /* Name of the statement journal file */ + sqlite3_file *fd, *jfd; /* File descriptors for database and journal */ + sqlite3_file *stfd; /* File descriptor for the statement subjournal*/ + BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ + PagerLruList lru; /* LRU list of free pages */ + PgHdr *pAll; /* List of all pages */ + PgHdr *pStmt; /* List of pages in the statement subjournal */ + PgHdr *pDirty; /* List of all dirty pages */ + i64 journalOff; /* Current byte offset in the journal file */ + i64 journalHdr; /* Byte offset to previous journal header */ + i64 stmtHdrOff; /* First journal header written this statement */ + i64 stmtCksum; /* cksumInit when statement was started */ + i64 stmtJSize; /* Size of journal at stmt_begin() */ + int sectorSize; /* Assumed sector size during rollback */ +#ifdef SQLITE_TEST + int nHit, nMiss; /* Cache hits and missing */ + int nRead, nWrite; /* Database pages read/written */ +#endif + void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */ + void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */ +#ifdef SQLITE_HAS_CODEC + void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ + void *pCodecArg; /* First argument to xCodec() */ +#endif + int nHash; /* Size of the pager hash table */ + PgHdr **aHash; /* Hash table to map page number to PgHdr */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Pager *pNext; /* Doubly linked list of pagers on which */ + Pager *pPrev; /* sqlite3_release_memory() will work */ + int iInUseMM; /* Non-zero if unavailable to MM */ + int iInUseDB; /* Non-zero if in sqlite3_release_memory() */ +#endif + char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ + char dbFileVers[16]; /* Changes whenever database file changes */ +}; + +/* +** The following global variables hold counters used for +** testing purposes only. These variables do not exist in +** a non-testing build. These variables are not thread-safe. +*/ +#ifdef SQLITE_TEST +int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ +int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ +int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ +int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */ +# define PAGER_INCR(v) v++ +#else +# define PAGER_INCR(v) +#endif + +/* +** The following variable points to the head of a double-linked list +** of all pagers that are eligible for page stealing by the +** sqlite3_release_memory() interface. Access to this list is +** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +static Pager *sqlite3PagerList = 0; +static PagerLruList sqlite3LruPageList = {0, 0, 0}; +#endif + + +/* +** Journal files begin with the following magic string. The data +** was obtained from /dev/random. It is used only as a sanity check. +** +** Since version 2.8.0, the journal format contains additional sanity +** checking information. If the power fails while the journal is begin +** written, semi-random garbage data might appear in the journal +** file after power is restored. If an attempt is then made +** to roll the journal back, the database could be corrupted. The additional +** sanity checking data is an attempt to discover the garbage in the +** journal and ignore it. +** +** The sanity checking information for the new journal format consists +** of a 32-bit checksum on each page of data. The checksum covers both +** the page number and the pPager->pageSize bytes of data for the page. +** This cksum is initialized to a 32-bit random value that appears in the +** journal file right after the header. The random initializer is important, +** because garbage data that appears at the end of a journal is likely +** data that was once in other files that have now been deleted. If the +** garbage data came from an obsolete journal file, the checksums might +** be correct. But by initializing the checksum to random value which +** is different for every journal, we minimize that risk. +*/ +static const unsigned char aJournalMagic[] = { + 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, +}; + +/* +** The size of the header and of each page in the journal is determined +** by the following macros. +*/ +#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) + +/* +** The journal header size for this pager. In the future, this could be +** set to some value read from the disk controller. The important +** characteristic is that it is the same size as a disk sector. +*/ +#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) + +/* +** The macro MEMDB is true if we are dealing with an in-memory database. +** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, +** the value of MEMDB will be a constant and the compiler will optimize +** out code that would never execute. +*/ +#ifdef SQLITE_OMIT_MEMORYDB +# define MEMDB 0 +#else +# define MEMDB pPager->memDb +#endif + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() for details. +*/ +/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */ +#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1) + +/* +** The maximum legal page number is (2^31 - 1). +*/ +#define PAGER_MAX_PGNO 2147483647 + +/* +** The pagerEnter() and pagerLeave() routines acquire and release +** a mutex on each pager. The mutex is recursive. +** +** This is a special-purpose mutex. It only provides mutual exclusion +** between the Btree and the Memory Management sqlite3_release_memory() +** function. It does not prevent, for example, two Btrees from accessing +** the same pager at the same time. Other general-purpose mutexes in +** the btree layer handle that chore. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + static void pagerEnter(Pager *p){ + p->iInUseDB++; + if( p->iInUseMM && p->iInUseDB==1 ){ + sqlite3_mutex *mutex; + mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + p->iInUseDB = 0; + sqlite3_mutex_enter(mutex); + p->iInUseDB = 1; + sqlite3_mutex_leave(mutex); + } + assert( p->iInUseMM==0 ); + } + static void pagerLeave(Pager *p){ + p->iInUseDB--; + assert( p->iInUseDB>=0 ); + } +#else +# define pagerEnter(X) +# define pagerLeave(X) +#endif + +/* +** Add page pPg to the end of the linked list managed by structure +** pList (pPg becomes the last entry in the list - the most recently +** used). Argument pLink should point to either pPg->free or pPg->gfree, +** depending on whether pPg is being added to the pager-specific or +** global LRU list. +*/ +static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ + pLink->pNext = 0; + pLink->pPrev = pList->pLast; + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + assert(pLink==&pPg->free || pLink==&pPg->gfree); + assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList); +#endif + + if( pList->pLast ){ + int iOff = (char *)pLink - (char *)pPg; + PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]); + pLastLink->pNext = pPg; + }else{ + assert(!pList->pFirst); + pList->pFirst = pPg; + } + + pList->pLast = pPg; + if( !pList->pFirstSynced && pPg->needSync==0 ){ + pList->pFirstSynced = pPg; + } +} + +/* +** Remove pPg from the list managed by the structure pointed to by pList. +** +** Argument pLink should point to either pPg->free or pPg->gfree, depending +** on whether pPg is being added to the pager-specific or global LRU list. +*/ +static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ + int iOff = (char *)pLink - (char *)pPg; + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + assert(pLink==&pPg->free || pLink==&pPg->gfree); + assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList); +#endif + + if( pPg==pList->pFirst ){ + pList->pFirst = pLink->pNext; + } + if( pPg==pList->pLast ){ + pList->pLast = pLink->pPrev; + } + if( pLink->pPrev ){ + PagerLruLink *pPrevLink = (PagerLruLink *)(&((u8 *)pLink->pPrev)[iOff]); + pPrevLink->pNext = pLink->pNext; + } + if( pLink->pNext ){ + PagerLruLink *pNextLink = (PagerLruLink *)(&((u8 *)pLink->pNext)[iOff]); + pNextLink->pPrev = pLink->pPrev; + } + if( pPg==pList->pFirstSynced ){ + PgHdr *p = pLink->pNext; + while( p && p->needSync ){ + PagerLruLink *pL = (PagerLruLink *)(&((u8 *)p)[iOff]); + p = pL->pNext; + } + pList->pFirstSynced = p; + } + + pLink->pNext = pLink->pPrev = 0; +} + +/* +** Add page pPg to the list of free pages for the pager. If +** memory-management is enabled, also add the page to the global +** list of free pages. +*/ +static void lruListAdd(PgHdr *pPg){ + listAdd(&pPg->pPager->lru, &pPg->free, pPg); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !pPg->pPager->memDb ){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + listAdd(&sqlite3LruPageList, &pPg->gfree, pPg); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + } +#endif +} + +/* +** Remove page pPg from the list of free pages for the associated pager. +** If memory-management is enabled, also remove pPg from the global list +** of free pages. +*/ +static void lruListRemove(PgHdr *pPg){ + listRemove(&pPg->pPager->lru, &pPg->free, pPg); +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !pPg->pPager->memDb ){ + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + listRemove(&sqlite3LruPageList, &pPg->gfree, pPg); + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + } +#endif +} + +/* +** This function is called just after the needSync flag has been cleared +** from all pages managed by pPager (usually because the journal file +** has just been synced). It updates the pPager->lru.pFirstSynced variable +** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced +** variable also. +*/ +static void lruListSetFirstSynced(Pager *pPager){ + pPager->lru.pFirstSynced = pPager->lru.pFirst; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !pPager->memDb ){ + PgHdr *p; + sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext); + assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced); + sqlite3LruPageList.pFirstSynced = p; + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + } +#endif +} + +/* +** Return true if page *pPg has already been written to the statement +** journal (or statement snapshot has been created, if *pPg is part +** of an in-memory database). +*/ +static int pageInStatement(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + if( MEMDB ){ + return PGHDR_TO_HIST(pPg, pPager)->inStmt; + }else{ + Pgno pgno = pPg->pgno; + u8 *a = pPager->aInStmt; + return (a && (int)pgno<=pPager->stmtSize && (a[pgno/8] & (1<<(pgno&7)))); + } +} + +/* +** Change the size of the pager hash table to N. N must be a power +** of two. +*/ +static void pager_resize_hash_table(Pager *pPager, int N){ + PgHdr **aHash, *pPg; + assert( N>0 && (N&(N-1))==0 ); + pagerLeave(pPager); + sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pPager->aHash!=0); + aHash = sqlite3MallocZero( sizeof(aHash[0])*N ); + sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0); + pagerEnter(pPager); + if( aHash==0 ){ + /* Failure to rehash is not an error. It is only a performance hit. */ + return; + } + sqlite3_free(pPager->aHash); + pPager->nHash = N; + pPager->aHash = aHash; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + int h; + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + continue; + } + h = pPg->pgno & (N-1); + pPg->pNextHash = aHash[h]; + if( aHash[h] ){ + aHash[h]->pPrevHash = pPg; + } + aHash[h] = pPg; + pPg->pPrevHash = 0; + } +} + +/* +** Read a 32-bit integer from the given file descriptor. Store the integer +** that is read in *pRes. Return SQLITE_OK if everything worked, or an +** error code is something goes wrong. +** +** All values are stored on disk as big-endian. +*/ +static int read32bits(sqlite3_file *fd, i64 offset, u32 *pRes){ + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset); + if( rc==SQLITE_OK ){ + *pRes = sqlite3Get4byte(ac); + } + return rc; +} + +/* +** Write a 32-bit integer into a string buffer in big-endian byte order. +*/ +#define put32bits(A,B) sqlite3Put4byte((u8*)A,B) + +/* +** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK +** on success or an error code is something goes wrong. +*/ +static int write32bits(sqlite3_file *fd, i64 offset, u32 val){ + char ac[4]; + put32bits(ac, val); + return sqlite3OsWrite(fd, ac, 4, offset); +} + +/* +** If file pFd is open, call sqlite3OsUnlock() on it. +*/ +static int osUnlock(sqlite3_file *pFd, int eLock){ + if( !pFd->pMethods ){ + return SQLITE_OK; + } + return sqlite3OsUnlock(pFd, eLock); +} + +/* +** This function determines whether or not the atomic-write optimization +** can be used with this pager. The optimization can be used if: +** +** (a) the value returned by OsDeviceCharacteristics() indicates that +** a database page may be written atomically, and +** (b) the value returned by OsSectorSize() is less than or equal +** to the page size. +** +** If the optimization cannot be used, 0 is returned. If it can be used, +** then the value returned is the size of the journal file when it +** contains rollback data for exactly one page. +*/ +#ifdef SQLITE_ENABLE_ATOMIC_WRITE +static int jrnlBufferSize(Pager *pPager){ + int dc; /* Device characteristics */ + int nSector; /* Sector size */ + int nPage; /* Page size */ + sqlite3_file *fd = pPager->fd; + + if( fd->pMethods ){ + dc = sqlite3OsDeviceCharacteristics(fd); + nSector = sqlite3OsSectorSize(fd); + nPage = pPager->pageSize; + } + + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + + if( !fd->pMethods || (dc&(SQLITE_IOCAP_ATOMIC|(nPage>>8))&&nSector<=nPage) ){ + return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager); + } + return 0; +} +#endif + +/* +** This function should be called when an error occurs within the pager +** code. The first argument is a pointer to the pager structure, the +** second the error-code about to be returned by a pager API function. +** The value returned is a copy of the second argument to this function. +** +** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL +** the error becomes persistent. Until the persisten error is cleared, +** subsequent API calls on this Pager will immediately return the same +** error code. +** +** A persistent error indicates that the contents of the pager-cache +** cannot be trusted. This state can be cleared by completely discarding +** the contents of the pager-cache. If a transaction was active when +** the persistent error occured, then the rollback journal may need +** to be replayed. +*/ +static void pager_unlock(Pager *pPager); +static int pager_error(Pager *pPager, int rc){ + int rc2 = rc & 0xff; + assert( + pPager->errCode==SQLITE_FULL || + pPager->errCode==SQLITE_OK || + (pPager->errCode & 0xff)==SQLITE_IOERR + ); + if( + rc2==SQLITE_FULL || + rc2==SQLITE_IOERR || + rc2==SQLITE_CORRUPT + ){ + pPager->errCode = rc; + if( pPager->state==PAGER_UNLOCK && pPager->nRef==0 ){ + /* If the pager is already unlocked, call pager_unlock() now to + ** clear the error state and ensure that the pager-cache is + ** completely empty. + */ + pager_unlock(pPager); + } + } + return rc; +} + +/* +** If SQLITE_CHECK_PAGES is defined then we do some sanity checking +** on the cache using a hash function. This is used for testing +** and debugging only. +*/ +#ifdef SQLITE_CHECK_PAGES +/* +** Return a 32-bit hash of the page data for pPage. +*/ +static u32 pager_datahash(int nByte, unsigned char *pData){ + u32 hash = 0; + int i; + for(i=0; ipPager->pageSize, + (unsigned char *)PGHDR_TO_DATA(pPage)); +} + +/* +** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES +** is defined, and NDEBUG is not defined, an assert() statement checks +** that the page is either dirty or still matches the calculated page-hash. +*/ +#define CHECK_PAGE(x) checkPage(x) +static void checkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || + pPg->pageHash==pager_pagehash(pPg) ); +} + +#else +#define pager_datahash(X,Y) 0 +#define pager_pagehash(X) 0 +#define CHECK_PAGE(x) +#endif + +/* +** When this is called the journal file for pager pPager must be open. +** The master journal file name is read from the end of the file and +** written into memory supplied by the caller. +** +** zMaster must point to a buffer of at least nMaster bytes allocated by +** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is +** enough space to write the master journal name). If the master journal +** name in the journal is longer than nMaster bytes (including a +** nul-terminator), then this is handled as if no master journal name +** were present in the journal. +** +** If no master journal file name is present zMaster[0] is set to 0 and +** SQLITE_OK returned. +*/ +static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){ + int rc; + u32 len; + i64 szJ; + u32 cksum; + int i; + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + + zMaster[0] = '\0'; + + rc = sqlite3OsFileSize(pJrnl, &szJ); + if( rc!=SQLITE_OK || szJ<16 ) return rc; + + rc = read32bits(pJrnl, szJ-16, &len); + if( rc!=SQLITE_OK ) return rc; + + if( len>=nMaster ){ + return SQLITE_OK; + } + + rc = read32bits(pJrnl, szJ-12, &cksum); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8); + if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; + + rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len); + if( rc!=SQLITE_OK ){ + return rc; + } + zMaster[len] = '\0'; + + /* See if the checksum matches the master journal name */ + for(i=0; ijournalOff; + if( c ){ + offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); + } + assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); + assert( offset>=c ); + assert( (offset-c)journalOff = offset; +} + +/* +** The journal file must be open when this routine is called. A journal +** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the +** current location. +** +** The format for the journal header is as follows: +** - 8 bytes: Magic identifying journal format. +** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. +** - 4 bytes: Random number used for page hash. +** - 4 bytes: Initial database page count. +** - 4 bytes: Sector size used by the process that wrote this journal. +** +** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space. +*/ +static int writeJournalHdr(Pager *pPager){ + char zHeader[sizeof(aJournalMagic)+16]; + int rc; + + if( pPager->stmtHdrOff==0 ){ + pPager->stmtHdrOff = pPager->journalOff; + } + + seekJournalHdr(pPager); + pPager->journalHdr = pPager->journalOff; + + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + + /* + ** Write the nRec Field - the number of page records that follow this + ** journal header. Normally, zero is written to this value at this time. + ** After the records are added to the journal (and the journal synced, + ** if in full-sync mode), the zero is overwritten with the true number + ** of records (see syncJournal()). + ** + ** A faster alternative is to write 0xFFFFFFFF to the nRec field. When + ** reading the journal this value tells SQLite to assume that the + ** rest of the journal file contains valid page records. This assumption + ** is dangerous, as if a failure occured whilst writing to the journal + ** file it may contain some garbage data. There are two scenarios + ** where this risk can be ignored: + ** + ** * When the pager is in no-sync mode. Corruption can follow a + ** power failure in this case anyway. + ** + ** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees + ** that garbage data is never appended to the journal file. + */ + assert(pPager->fd->pMethods||pPager->noSync); + if( (pPager->noSync) + || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) + ){ + put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); + }else{ + put32bits(&zHeader[sizeof(aJournalMagic)], 0); + } + + /* The random check-hash initialiser */ + sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); + /* The initial database size */ + put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize); + /* The assumed sector size for this process */ + put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); + IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader))) + rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader),pPager->journalOff); + pPager->journalOff += JOURNAL_HDR_SZ(pPager); + + /* The journal header has been written successfully. Seek the journal + ** file descriptor to the end of the journal header sector. + */ + if( rc==SQLITE_OK ){ + IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1)) + rc = sqlite3OsWrite(pPager->jfd, "\000", 1, pPager->journalOff-1); + } + return rc; +} + +/* +** The journal file must be open when this is called. A journal header file +** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal +** file. See comments above function writeJournalHdr() for a description of +** the journal header format. +** +** If the header is read successfully, *nRec is set to the number of +** page records following this header and *dbSize is set to the size of the +** database before the transaction began, in pages. Also, pPager->cksumInit +** is set to the value read from the journal header. SQLITE_OK is returned +** in this case. +** +** If the journal header file appears to be corrupted, SQLITE_DONE is +** returned and *nRec and *dbSize are not set. If JOURNAL_HDR_SZ bytes +** cannot be read from the journal file an error code is returned. +*/ +static int readJournalHdr( + Pager *pPager, + i64 journalSize, + u32 *pNRec, + u32 *pDbSize +){ + int rc; + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + i64 jrnlOff; + + seekJournalHdr(pPager); + if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ + return SQLITE_DONE; + } + jrnlOff = pPager->journalOff; + + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), jrnlOff); + if( rc ) return rc; + jrnlOff += sizeof(aMagic); + + if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ + return SQLITE_DONE; + } + + rc = read32bits(pPager->jfd, jrnlOff, pNRec); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, jrnlOff+4, &pPager->cksumInit); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize); + if( rc ) return rc; + + /* Update the assumed sector-size to match the value used by + ** the process that created this journal. If this journal was + ** created by a process other than this one, then this routine + ** is being called from within pager_playback(). The local value + ** of Pager.sectorSize is restored at the end of that routine. + */ + rc = read32bits(pPager->jfd, jrnlOff+12, (u32 *)&pPager->sectorSize); + if( rc ) return rc; + + pPager->journalOff += JOURNAL_HDR_SZ(pPager); + return SQLITE_OK; +} + + +/* +** Write the supplied master journal name into the journal file for pager +** pPager at the current location. The master journal name must be the last +** thing written to a journal file. If the pager is in full-sync mode, the +** journal file descriptor is advanced to the next sector boundary before +** anything is written. The format is: +** +** + 4 bytes: PAGER_MJ_PGNO. +** + N bytes: length of master journal name. +** + 4 bytes: N +** + 4 bytes: Master journal name checksum. +** + 8 bytes: aJournalMagic[]. +** +** The master journal page checksum is the sum of the bytes in the master +** journal name. +** +** If zMaster is a NULL pointer (occurs for a single database transaction), +** this call is a no-op. +*/ +static int writeMasterJournal(Pager *pPager, const char *zMaster){ + int rc; + int len; + int i; + i64 jrnlOff; + u32 cksum = 0; + char zBuf[sizeof(aJournalMagic)+2*4]; + + if( !zMaster || pPager->setMaster) return SQLITE_OK; + pPager->setMaster = 1; + + len = strlen(zMaster); + for(i=0; ifullSync ){ + seekJournalHdr(pPager); + } + jrnlOff = pPager->journalOff; + pPager->journalOff += (len+20); + + rc = write32bits(pPager->jfd, jrnlOff, PAGER_MJ_PGNO(pPager)); + if( rc!=SQLITE_OK ) return rc; + jrnlOff += 4; + + rc = sqlite3OsWrite(pPager->jfd, zMaster, len, jrnlOff); + if( rc!=SQLITE_OK ) return rc; + jrnlOff += len; + + put32bits(zBuf, len); + put32bits(&zBuf[4], cksum); + memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic), jrnlOff); + pPager->needSync = !pPager->noSync; + return rc; +} + +/* +** Add or remove a page from the list of all pages that are in the +** statement journal. +** +** The Pager keeps a separate list of pages that are currently in +** the statement journal. This helps the sqlite3PagerStmtCommit() +** routine run MUCH faster for the common case where there are many +** pages in memory but only a few are in the statement journal. +*/ +static void page_add_to_stmt_list(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( MEMDB ); + if( !pHist->inStmt ){ + assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 ); + if( pPager->pStmt ){ + PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg; + } + pHist->pNextStmt = pPager->pStmt; + pPager->pStmt = pPg; + pHist->inStmt = 1; + } +} + +/* +** Find a page in the hash table given its page number. Return +** a pointer to the page or NULL if not found. +*/ +static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ + PgHdr *p; + if( pPager->aHash==0 ) return 0; + p = pPager->aHash[pgno & (pPager->nHash-1)]; + while( p && p->pgno!=pgno ){ + p = p->pNextHash; + } + return p; +} + +/* +** Clear the in-memory cache. This routine +** sets the state of the pager back to what it was when it was first +** opened. Any outstanding pages are invalidated and subsequent attempts +** to access those pages will likely result in a coredump. +*/ +static void pager_reset(Pager *pPager){ + PgHdr *pPg, *pNext; + if( pPager->errCode ) return; + for(pPg=pPager->pAll; pPg; pPg=pNext){ + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + pNext = pPg->pNextAll; + lruListRemove(pPg); + sqlite3_free(pPg); + } + assert(pPager->lru.pFirst==0); + assert(pPager->lru.pFirstSynced==0); + assert(pPager->lru.pLast==0); + pPager->pStmt = 0; + pPager->pAll = 0; + pPager->pDirty = 0; + pPager->nHash = 0; + sqlite3_free(pPager->aHash); + pPager->nPage = 0; + pPager->aHash = 0; + pPager->nRef = 0; +} + +/* +** Unlock the database file. +** +** If the pager is currently in error state, discard the contents of +** the cache and reset the Pager structure internal state. If there is +** an open journal-file, then the next time a shared-lock is obtained +** on the pager file (by this or any other process), it will be +** treated as a hot-journal and rolled back. +*/ +static void pager_unlock(Pager *pPager){ + if( !pPager->exclusiveMode ){ + if( !MEMDB ){ + if( pPager->fd->pMethods ){ + osUnlock(pPager->fd, NO_LOCK); + } + pPager->dbSize = -1; + IOTRACE(("UNLOCK %p\n", pPager)) + + /* If Pager.errCode is set, the contents of the pager cache cannot be + ** trusted. Now that the pager file is unlocked, the contents of the + ** cache can be discarded and the error code safely cleared. + */ + if( pPager->errCode ){ + pPager->errCode = SQLITE_OK; + pager_reset(pPager); + if( pPager->stmtOpen ){ + sqlite3OsClose(pPager->stfd); + sqlite3_free(pPager->aInStmt); + pPager->aInStmt = 0; + } + if( pPager->journalOpen ){ + sqlite3OsClose(pPager->jfd); + pPager->journalOpen = 0; + sqlite3_free(pPager->aInJournal); + pPager->aInJournal = 0; + } + pPager->stmtOpen = 0; + pPager->stmtInUse = 0; + pPager->journalOff = 0; + pPager->journalStarted = 0; + pPager->stmtAutoopen = 0; + pPager->origDbSize = 0; + } + } + + if( !MEMDB || pPager->errCode==SQLITE_OK ){ + pPager->state = PAGER_UNLOCK; + pPager->changeCountDone = 0; + } + } +} + +/* +** Execute a rollback if a transaction is active and unlock the +** database file. If the pager has already entered the error state, +** do not attempt the rollback. +*/ +static void pagerUnlockAndRollback(Pager *p){ + assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); + if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){ + sqlite3PagerRollback(p); + } + pager_unlock(p); + assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) ); + assert( p->errCode || !p->stmtOpen || p->exclusiveMode ); +} + +/* +** This routine ends a transaction. A transaction is ended by either +** a COMMIT or a ROLLBACK. +** +** When this routine is called, the pager has the journal file open and +** a RESERVED or EXCLUSIVE lock on the database. This routine will release +** the database lock and acquires a SHARED lock in its place if that is +** the appropriate thing to do. Release locks usually is appropriate, +** unless we are in exclusive access mode or unless this is a +** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation. +** +** The journal file is either deleted or truncated. +** +** TODO: Consider keeping the journal file open for temporary databases. +** This might give a performance improvement on windows where opening +** a file is an expensive operation. +*/ +static int pager_end_transaction(Pager *pPager){ + PgHdr *pPg; + int rc = SQLITE_OK; + int rc2 = SQLITE_OK; + assert( !MEMDB ); + if( pPager->statestmtOpen && !pPager->exclusiveMode ){ + sqlite3OsClose(pPager->stfd); + pPager->stmtOpen = 0; + } + if( pPager->journalOpen ){ + if( pPager->exclusiveMode + && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){; + pPager->journalOff = 0; + pPager->journalStarted = 0; + }else{ + sqlite3OsClose(pPager->jfd); + pPager->journalOpen = 0; + if( rc==SQLITE_OK ){ + rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); + } + } + sqlite3_free( pPager->aInJournal ); + pPager->aInJournal = 0; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + pPg->inJournal = 0; + pPg->dirty = 0; + pPg->needSync = 0; + pPg->alwaysRollback = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + } + pPager->pDirty = 0; + pPager->dirtyCache = 0; + pPager->nRec = 0; + }else{ + assert( pPager->aInJournal==0 ); + assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); + } + + if( !pPager->exclusiveMode ){ + rc2 = osUnlock(pPager->fd, SHARED_LOCK); + pPager->state = PAGER_SHARED; + }else if( pPager->state==PAGER_SYNCED ){ + pPager->state = PAGER_EXCLUSIVE; + } + pPager->origDbSize = 0; + pPager->setMaster = 0; + pPager->needSync = 0; + lruListSetFirstSynced(pPager); + pPager->dbSize = -1; + + return (rc==SQLITE_OK?rc2:rc); +} + +/* +** Compute and return a checksum for the page of data. +** +** This is not a real checksum. It is really just the sum of the +** random initial value and the page number. We experimented with +** a checksum of the entire data, but that was found to be too slow. +** +** Note that the page number is stored at the beginning of data and +** the checksum is stored at the end. This is important. If journal +** corruption occurs due to a power failure, the most likely scenario +** is that one end or the other of the record will be changed. It is +** much less likely that the two ends of the journal record will be +** correct and the middle be corrupt. Thus, this "checksum" scheme, +** though fast and simple, catches the mostly likely kind of corruption. +** +** FIX ME: Consider adding every 200th (or so) byte of the data to the +** checksum. That way if a single page spans 3 or more disk sectors and +** only the middle sector is corrupt, we will still have a reasonable +** chance of failing the checksum and thus detecting the problem. +*/ +static u32 pager_cksum(Pager *pPager, const u8 *aData){ + u32 cksum = pPager->cksumInit; + int i = pPager->pageSize-200; + while( i>0 ){ + cksum += aData[i]; + i -= 200; + } + return cksum; +} + +/* Forward declaration */ +static void makeClean(PgHdr*); + +/* +** Read a single page from the journal file opened on file descriptor +** jfd. Playback this one page. +** +** If useCksum==0 it means this journal does not use checksums. Checksums +** are not used in statement journals because statement journals do not +** need to survive power failures. +*/ +static int pager_playback_one_page( + Pager *pPager, + sqlite3_file *jfd, + i64 offset, + int useCksum +){ + int rc; + PgHdr *pPg; /* An existing page in the cache */ + Pgno pgno; /* The page number of a page in journal */ + u32 cksum; /* Checksum used for sanity checking */ + u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */ + + /* useCksum should be true for the main journal and false for + ** statement journals. Verify that this is always the case + */ + assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) ); + assert( aData ); + + rc = read32bits(jfd, offset, &pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4); + if( rc!=SQLITE_OK ) return rc; + pPager->journalOff += pPager->pageSize + 4; + + /* Sanity checking on the page. This is more important that I originally + ** thought. If a power failure occurs while the journal is being written, + ** it could cause invalid data to be written into the journal. We need to + ** detect this invalid data (with high probability) and ignore it. + */ + if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + return SQLITE_DONE; + } + if( pgno>(unsigned)pPager->dbSize ){ + return SQLITE_OK; + } + if( useCksum ){ + rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum); + if( rc ) return rc; + pPager->journalOff += 4; + if( pager_cksum(pPager, aData)!=cksum ){ + return SQLITE_DONE; + } + } + + assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE ); + + /* If the pager is in RESERVED state, then there must be a copy of this + ** page in the pager cache. In this case just update the pager cache, + ** not the database file. The page is left marked dirty in this case. + ** + ** An exception to the above rule: If the database is in no-sync mode + ** and a page is moved during an incremental vacuum then the page may + ** not be in the pager cache. Later: if a malloc() or IO error occurs + ** during a Movepage() call, then the page may not be in the cache + ** either. So the condition described in the above paragraph is not + ** assert()able. + ** + ** If in EXCLUSIVE state, then we update the pager cache if it exists + ** and the main file. The page is then marked not dirty. + ** + ** Ticket #1171: The statement journal might contain page content that is + ** different from the page content at the start of the transaction. + ** This occurs when a page is changed prior to the start of a statement + ** then changed again within the statement. When rolling back such a + ** statement we must not write to the original database unless we know + ** for certain that original page contents are synced into the main rollback + ** journal. Otherwise, a power loss might leave modified data in the + ** database file without an entry in the rollback journal that can + ** restore the database to its original form. Two conditions must be + ** met before writing to the database files. (1) the database must be + ** locked. (2) we know that the original page content is fully synced + ** in the main journal either because the page is not in cache or else + ** the page is marked as needSync==0. + */ + pPg = pager_lookup(pPager, pgno); + PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n", + PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData)); + if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ + i64 offset = (pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset); + if( pPg ){ + makeClean(pPg); + } + } + if( pPg ){ + /* No page should ever be explicitly rolled back that is in use, except + ** for page 1 which is held in use in order to keep the lock on the + ** database active. However such a page may be rolled back as a result + ** of an internal error resulting in an automatic call to + ** sqlite3PagerRollback(). + */ + void *pData; + /* assert( pPg->nRef==0 || pPg->pgno==1 ); */ + pData = PGHDR_TO_DATA(pPg); + memcpy(pData, aData, pPager->pageSize); + if( pPager->xReiniter ){ + pPager->xReiniter(pPg, pPager->pageSize); + } +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + /* If this was page 1, then restore the value of Pager.dbFileVers. + ** Do this before any decoding. */ + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); + } + + /* Decode the page just read from disk */ + CODEC1(pPager, pData, pPg->pgno, 3); + } + return rc; +} + +/* +** Parameter zMaster is the name of a master journal file. A single journal +** file that referred to the master journal file has just been rolled back. +** This routine checks if it is possible to delete the master journal file, +** and does so if it is. +** +** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not +** available for use within this function. +** +** +** The master journal file contains the names of all child journals. +** To tell if a master journal can be deleted, check to each of the +** children. If all children are either missing or do not refer to +** a different master journal, then this master journal can be deleted. +*/ +static int pager_delmaster(Pager *pPager, const char *zMaster){ + sqlite3_vfs *pVfs = pPager->pVfs; + int rc; + int master_open = 0; + sqlite3_file *pMaster; + sqlite3_file *pJournal; + char *zMasterJournal = 0; /* Contents of master journal file */ + i64 nMasterJournal; /* Size of master journal file */ + + /* Open the master journal file exclusively in case some other process + ** is running this routine also. Not that it makes too much difference. + */ + pMaster = (sqlite3_file *)sqlite3_malloc(pVfs->szOsFile * 2); + pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile); + if( !pMaster ){ + rc = SQLITE_NOMEM; + }else{ + int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL); + rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0); + } + if( rc!=SQLITE_OK ) goto delmaster_out; + master_open = 1; + + rc = sqlite3OsFileSize(pMaster, &nMasterJournal); + if( rc!=SQLITE_OK ) goto delmaster_out; + + if( nMasterJournal>0 ){ + char *zJournal; + char *zMasterPtr = 0; + int nMasterPtr = pPager->pVfs->mxPathname+1; + + /* Load the entire master journal file into space obtained from + ** sqlite3_malloc() and pointed to by zMasterJournal. + */ + zMasterJournal = (char *)sqlite3_malloc(nMasterJournal + nMasterPtr); + if( !zMasterJournal ){ + rc = SQLITE_NOMEM; + goto delmaster_out; + } + zMasterPtr = &zMasterJournal[nMasterJournal]; + rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0); + if( rc!=SQLITE_OK ) goto delmaster_out; + + zJournal = zMasterJournal; + while( (zJournal-zMasterJournal)state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){ + i64 currentSize, newSize; + rc = sqlite3OsFileSize(pPager->fd, ¤tSize); + newSize = pPager->pageSize*(i64)nPage; + if( rc==SQLITE_OK && currentSize>newSize ){ + rc = sqlite3OsTruncate(pPager->fd, newSize); + } + } + if( rc==SQLITE_OK ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + } + return rc; +} + +/* +** Set the sectorSize for the given pager. +** +** The sector size is the larger of the sector size reported +** by sqlite3OsSectorSize() and the pageSize. +*/ +static void setSectorSize(Pager *pPager){ + assert(pPager->fd->pMethods||pPager->tempFile); + if( !pPager->tempFile ){ + /* Sector size doesn't matter for temporary files. Also, the file + ** may not have been opened yet, in whcih case the OsSectorSize() + ** call will segfault. + */ + pPager->sectorSize = sqlite3OsSectorSize(pPager->fd); + } + if( pPager->sectorSizepageSize ){ + pPager->sectorSize = pPager->pageSize; + } +} + +/* +** Playback the journal and thus restore the database file to +** the state it was in before we started making changes. +** +** The journal file format is as follows: +** +** (1) 8 byte prefix. A copy of aJournalMagic[]. +** (2) 4 byte big-endian integer which is the number of valid page records +** in the journal. If this value is 0xffffffff, then compute the +** number of page records from the journal size. +** (3) 4 byte big-endian integer which is the initial value for the +** sanity checksum. +** (4) 4 byte integer which is the number of pages to truncate the +** database to during a rollback. +** (5) 4 byte integer which is the number of bytes in the master journal +** name. The value may be zero (indicate that there is no master +** journal.) +** (6) N bytes of the master journal name. The name will be nul-terminated +** and might be shorter than the value read from (5). If the first byte +** of the name is \000 then there is no master journal. The master +** journal name is stored in UTF-8. +** (7) Zero or more pages instances, each as follows: +** + 4 byte page number. +** + pPager->pageSize bytes of data. +** + 4 byte checksum +** +** When we speak of the journal header, we mean the first 6 items above. +** Each entry in the journal is an instance of the 7th item. +** +** Call the value from the second bullet "nRec". nRec is the number of +** valid page entries in the journal. In most cases, you can compute the +** value of nRec from the size of the journal file. But if a power +** failure occurred while the journal was being written, it could be the +** case that the size of the journal file had already been increased but +** the extra entries had not yet made it safely to disk. In such a case, +** the value of nRec computed from the file size would be too large. For +** that reason, we always use the nRec value in the header. +** +** If the nRec value is 0xffffffff it means that nRec should be computed +** from the file size. This value is used when the user selects the +** no-sync option for the journal. A power failure could lead to corruption +** in this case. But for things like temporary table (which will be +** deleted when the power is restored) we don't care. +** +** If the file opened as the journal file is not a well-formed +** journal file then all pages up to the first corrupted page are rolled +** back (or no pages if the journal header is corrupted). The journal file +** is then deleted and SQLITE_OK returned, just as if no corruption had +** been encountered. +** +** If an I/O or malloc() error occurs, the journal-file is not deleted +** and an error code is returned. +*/ +static int pager_playback(Pager *pPager, int isHot){ + sqlite3_vfs *pVfs = pPager->pVfs; + i64 szJ; /* Size of the journal file in bytes */ + u32 nRec; /* Number of Records in the journal */ + int i; /* Loop counter */ + Pgno mxPg = 0; /* Size of the original file in pages */ + int rc; /* Result code of a subroutine */ + char *zMaster = 0; /* Name of master journal file if any */ + + /* Figure out how many records are in the journal. Abort early if + ** the journal is empty. + */ + assert( pPager->journalOpen ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); + if( rc!=SQLITE_OK || szJ==0 ){ + goto end_playback; + } + + /* Read the master journal name from the journal, if it is present. + ** If a master journal file name is specified, but the file is not + ** present on disk, then the journal is not hot and does not need to be + ** played back. + */ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK + || (zMaster[0] && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS)) + ){ + zMaster = 0; + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + goto end_playback; + } + pPager->journalOff = 0; + zMaster = 0; + + /* This loop terminates either when the readJournalHdr() call returns + ** SQLITE_DONE or an IO error occurs. */ + while( 1 ){ + + /* Read the next journal header from the journal file. If there are + ** not enough bytes left in the journal file for a complete header, or + ** it is corrupted, then a process must of failed while writing it. + ** This indicates nothing more needs to be rolled back. + */ + rc = readJournalHdr(pPager, szJ, &nRec, &mxPg); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + } + goto end_playback; + } + + /* If nRec is 0xffffffff, then this journal was created by a process + ** working in no-sync mode. This means that the rest of the journal + ** file consists of pages, there are no more journal headers. Compute + ** the value of nRec based on this assumption. + */ + if( nRec==0xffffffff ){ + assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); + nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager); + } + + /* If nRec is 0 and this rollback is of a transaction created by this + ** process and if this is the final header in the journal, then it means + ** that this part of the journal was being filled but has not yet been + ** synced to disk. Compute the number of pages based on the remaining + ** size of the file. + ** + ** The third term of the test was added to fix ticket #2565. + */ + if( nRec==0 && !isHot && + pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){ + nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager); + } + + /* If this is the first header read from the journal, truncate the + ** database file back to its original size. + */ + if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ + rc = pager_truncate(pPager, mxPg); + if( rc!=SQLITE_OK ){ + goto end_playback; + } + } + + /* Copy original pages out of the journal and back into the database file. + */ + for(i=0; ijfd, pPager->journalOff, 1); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + pPager->journalOff = szJ; + break; + }else{ + goto end_playback; + } + } + } + } + /*NOTREACHED*/ + assert( 0 ); + +end_playback: + if( rc==SQLITE_OK ){ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + } + if( rc==SQLITE_OK ){ + rc = pager_end_transaction(pPager); + } + if( rc==SQLITE_OK && zMaster[0] ){ + /* If there was a master journal and this routine will return success, + ** see if it is possible to delete the master journal. + */ + rc = pager_delmaster(pPager, zMaster); + } + + /* The Pager.sectorSize variable may have been updated while rolling + ** back a journal created by a process with a different sector size + ** value. Reset it to the correct value for this process. + */ + setSectorSize(pPager); + return rc; +} + +/* +** Playback the statement journal. +** +** This is similar to playing back the transaction journal but with +** a few extra twists. +** +** (1) The number of pages in the database file at the start of +** the statement is stored in pPager->stmtSize, not in the +** journal file itself. +** +** (2) In addition to playing back the statement journal, also +** playback all pages of the transaction journal beginning +** at offset pPager->stmtJSize. +*/ +static int pager_stmt_playback(Pager *pPager){ + i64 szJ; /* Size of the full journal */ + i64 hdrOff; + int nRec; /* Number of Records */ + int i; /* Loop counter */ + int rc; + + szJ = pPager->journalOff; +#ifndef NDEBUG + { + i64 os_szJ; + rc = sqlite3OsFileSize(pPager->jfd, &os_szJ); + if( rc!=SQLITE_OK ) return rc; + assert( szJ==os_szJ ); + } +#endif + + /* Set hdrOff to be the offset just after the end of the last journal + ** page written before the first journal-header for this statement + ** transaction was written, or the end of the file if no journal + ** header was written. + */ + hdrOff = pPager->stmtHdrOff; + assert( pPager->fullSync || !hdrOff ); + if( !hdrOff ){ + hdrOff = szJ; + } + + /* Truncate the database back to its original size. + */ + rc = pager_truncate(pPager, pPager->stmtSize); + assert( pPager->state>=PAGER_SHARED ); + + /* Figure out how many records are in the statement journal. + */ + assert( pPager->stmtInUse && pPager->journalOpen ); + nRec = pPager->stmtNRec; + + /* Copy original pages out of the statement journal and back into the + ** database file. Note that the statement journal omits checksums from + ** each record since power-failure recovery is not important to statement + ** journals. + */ + for(i=0; ipageSize); + rc = pager_playback_one_page(pPager, pPager->stfd, offset, 0); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + + /* Now roll some pages back from the transaction journal. Pager.stmtJSize + ** was the size of the journal file when this statement was started, so + ** everything after that needs to be rolled back, either into the + ** database, the memory cache, or both. + ** + ** If it is not zero, then Pager.stmtHdrOff is the offset to the start + ** of the first journal header written during this statement transaction. + */ + pPager->journalOff = pPager->stmtJSize; + pPager->cksumInit = pPager->stmtCksum; + while( pPager->journalOff < hdrOff ){ + rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + + while( pPager->journalOff < szJ ){ + u32 nJRec; /* Number of Journal Records */ + u32 dummy; + rc = readJournalHdr(pPager, szJ, &nJRec, &dummy); + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_DONE ); + goto end_stmt_playback; + } + if( nJRec==0 ){ + nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); + } + for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){ + rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + } + + pPager->journalOff = szJ; + +end_stmt_playback: + if( rc==SQLITE_OK) { + pPager->journalOff = szJ; + /* pager_reload_cache(pPager); */ + } + return rc; +} + +/* +** Change the maximum number of in-memory pages that are allowed. +*/ +void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ + if( mxPage>10 ){ + pPager->mxPage = mxPage; + }else{ + pPager->mxPage = 10; + } +} + +/* +** Adjust the robustness of the database to damage due to OS crashes +** or power failures by changing the number of syncs()s when writing +** the rollback journal. There are three levels: +** +** OFF sqlite3OsSync() is never called. This is the default +** for temporary and transient files. +** +** NORMAL The journal is synced once before writes begin on the +** database. This is normally adequate protection, but +** it is theoretically possible, though very unlikely, +** that an inopertune power failure could leave the journal +** in a state which would cause damage to the database +** when it is rolled back. +** +** FULL The journal is synced twice before writes begin on the +** database (with some additional information - the nRec field +** of the journal header - being written in between the two +** syncs). If we assume that writing a +** single disk sector is atomic, then this mode provides +** assurance that the journal will not be corrupted to the +** point of causing damage to the database during rollback. +** +** Numeric values associated with these states are OFF==1, NORMAL=2, +** and FULL=3. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){ + pPager->noSync = level==1 || pPager->tempFile; + pPager->fullSync = level==3 && !pPager->tempFile; + pPager->sync_flags = (full_fsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL); + if( pPager->noSync ) pPager->needSync = 0; +} +#endif + +/* +** The following global variable is incremented whenever the library +** attempts to open a temporary file. This information is used for +** testing and analysis only. +*/ +#ifdef SQLITE_TEST +int sqlite3_opentemp_count = 0; +#endif + +/* +** Open a temporary file. +** +** Write the file descriptor into *fd. Return SQLITE_OK on success or some +** other error code if we fail. The OS will automatically delete the temporary +** file when it is closed. +*/ +static int sqlite3PagerOpentemp( + sqlite3_vfs *pVfs, /* The virtual file system layer */ + sqlite3_file *pFile, /* Write the file descriptor here */ + char *zFilename, /* Name of the file. Might be NULL */ + int vfsFlags /* Flags passed through to the VFS */ +){ + int rc; + assert( zFilename!=0 ); + +#ifdef SQLITE_TEST + sqlite3_opentemp_count++; /* Used for testing and analysis only */ +#endif + + vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE; + rc = sqlite3OsOpen(pVfs, zFilename, pFile, vfsFlags, 0); + assert( rc!=SQLITE_OK || pFile->pMethods ); + return rc; +} + +/* +** Create a new page cache and put a pointer to the page cache in *ppPager. +** The file to be cached need not exist. The file is not locked until +** the first call to sqlite3PagerGet() and is only held open until the +** last page is released using sqlite3PagerUnref(). +** +** If zFilename is NULL then a randomly-named temporary file is created +** and used as the file to be cached. The file will be deleted +** automatically when it is closed. +** +** If zFilename is ":memory:" then all information is held in cache. +** It is never written to disk. This can be used to implement an +** in-memory database. +*/ +int sqlite3PagerOpen( + sqlite3_vfs *pVfs, /* The virtual file system to use */ + Pager **ppPager, /* Return the Pager structure here */ + const char *zFilename, /* Name of the database file to open */ + int nExtra, /* Extra bytes append to each in-memory page */ + int flags, /* flags controlling this file */ + int vfsFlags /* flags passed through to sqlite3_vfs.xOpen() */ +){ + u8 *pPtr; + Pager *pPager = 0; + int rc = SQLITE_OK; + int i; + int tempFile = 0; + int memDb = 0; + int readOnly = 0; + int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; + int noReadlock = (flags & PAGER_NO_READLOCK)!=0; + int journalFileSize = sqlite3JournalSize(pVfs); + int nDefaultPage = SQLITE_DEFAULT_PAGE_SIZE; + char *zPathname; + int nPathname; + + /* The default return is a NULL pointer */ + *ppPager = 0; + + /* Compute the full pathname */ + nPathname = pVfs->mxPathname+1; + zPathname = sqlite3_malloc(nPathname); + if( zPathname==0 ){ + return SQLITE_NOMEM; + } + if( zFilename && zFilename[0] ){ +#ifndef SQLITE_OMIT_MEMORYDB + if( strcmp(zFilename,":memory:")==0 ){ + memDb = 1; + zPathname[0] = 0; + }else +#endif + { + rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname); + } + }else{ + rc = sqlite3OsGetTempname(pVfs, nPathname, zPathname); + } + if( rc!=SQLITE_OK ){ + sqlite3_free(zPathname); + return rc; + } + nPathname = strlen(zPathname); + + /* Allocate memory for the pager structure */ + pPager = sqlite3MallocZero( + sizeof(*pPager) + /* Pager structure */ + journalFileSize + /* The journal file structure */ + pVfs->szOsFile * 2 + /* The db and stmt journal files */ + 4*nPathname + 40 /* zFilename, zDirectory, zJournal, zStmtJrnl */ + ); + if( !pPager ){ + sqlite3_free(zPathname); + return SQLITE_NOMEM; + } + pPtr = (u8 *)&pPager[1]; + pPager->vfsFlags = vfsFlags; + pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0]; + pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1]; + pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2]; + pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize]; + pPager->zDirectory = &pPager->zFilename[nPathname+1]; + pPager->zJournal = &pPager->zDirectory[nPathname+1]; + pPager->zStmtJrnl = &pPager->zJournal[nPathname+10]; + pPager->pVfs = pVfs; + memcpy(pPager->zFilename, zPathname, nPathname+1); + sqlite3_free(zPathname); + + /* Open the pager file. + */ + if( zFilename && zFilename[0] && !memDb ){ + if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){ + rc = SQLITE_CANTOPEN; + }else{ + int fout = 0; + rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, + pPager->vfsFlags, &fout); + readOnly = (fout&SQLITE_OPEN_READONLY); + + /* If the file was successfully opened for read/write access, + ** choose a default page size in case we have to create the + ** database file. The default page size is the maximum of: + ** + ** + SQLITE_DEFAULT_PAGE_SIZE, + ** + The value returned by sqlite3OsSectorSize() + ** + The largest page size that can be written atomically. + */ + if( rc==SQLITE_OK && !readOnly ){ + int iSectorSize = sqlite3OsSectorSize(pPager->fd); + if( nDefaultPagefd); + int ii; + assert(SQLITE_IOCAP_ATOMIC512==(512>>8)); + assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8)); + assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536); + for(ii=nDefaultPage; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){ + if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ) nDefaultPage = ii; + } + } +#endif + if( nDefaultPage>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ + nDefaultPage = SQLITE_MAX_DEFAULT_PAGE_SIZE; + } + } + } + }else if( !memDb ){ + /* If a temporary file is requested, it is not opened immediately. + ** In this case we accept the default page size and delay actually + ** opening the file until the first call to OsWrite(). + */ + tempFile = 1; + pPager->state = PAGER_EXCLUSIVE; + } + + if( pPager && rc==SQLITE_OK ){ + pPager->pTmpSpace = (char *)sqlite3_malloc(nDefaultPage); + } + + /* If an error occured in either of the blocks above. + ** Free the Pager structure and close the file. + ** Since the pager is not allocated there is no need to set + ** any Pager.errMask variables. + */ + if( !pPager || !pPager->pTmpSpace ){ + sqlite3OsClose(pPager->fd); + sqlite3_free(pPager); + return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); + } + + PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename); + IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) + + /* Fill in Pager.zDirectory[] */ + memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1); + for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){} + if( i>0 ) pPager->zDirectory[i-1] = 0; + + /* Fill in Pager.zJournal[] and Pager.zStmtJrnl[] */ + memcpy(pPager->zJournal, pPager->zFilename, nPathname); + memcpy(&pPager->zJournal[nPathname], "-journal", 9); + memcpy(pPager->zStmtJrnl, pPager->zFilename, nPathname); + memcpy(&pPager->zStmtJrnl[nPathname], "-stmtjrnl", 10); + + /* pPager->journalOpen = 0; */ + pPager->useJournal = useJournal && !memDb; + pPager->noReadlock = noReadlock && readOnly; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ + pPager->dbSize = memDb-1; + pPager->pageSize = nDefaultPage; + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + pPager->mxPage = 100; + pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; + /* pPager->state = PAGER_UNLOCK; */ + assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) ); + /* pPager->errMask = 0; */ + pPager->tempFile = tempFile; + assert( tempFile==PAGER_LOCKINGMODE_NORMAL + || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); + pPager->exclusiveMode = tempFile; + pPager->memDb = memDb; + pPager->readOnly = readOnly; + /* pPager->needSync = 0; */ + pPager->noSync = pPager->tempFile || !useJournal; + pPager->fullSync = (pPager->noSync?0:1); + pPager->sync_flags = SQLITE_SYNC_NORMAL; + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ + pPager->nExtra = FORCE_ALIGNMENT(nExtra); + assert(pPager->fd->pMethods||memDb||tempFile); + if( !memDb ){ + setSectorSize(pPager); + } + /* pPager->pBusyHandler = 0; */ + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ + *ppPager = pPager; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pPager->iInUseMM = 0; + pPager->iInUseDB = 0; + if( !memDb ){ + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + sqlite3_mutex_enter(mutex); + pPager->pNext = sqlite3PagerList; + if( sqlite3PagerList ){ + assert( sqlite3PagerList->pPrev==0 ); + sqlite3PagerList->pPrev = pPager; + } + pPager->pPrev = 0; + sqlite3PagerList = pPager; + sqlite3_mutex_leave(mutex); + } +#endif + return SQLITE_OK; +} + +/* +** Set the busy handler function. +*/ +void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){ + pPager->pBusyHandler = pBusyHandler; +} + +/* +** Set the destructor for this pager. If not NULL, the destructor is called +** when the reference count on each page reaches zero. The destructor can +** be used to clean up information in the extra segment appended to each page. +** +** The destructor is not called as a result sqlite3PagerClose(). +** Destructors are only called by sqlite3PagerUnref(). +*/ +void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){ + pPager->xDestructor = xDesc; +} + +/* +** Set the reinitializer for this pager. If not NULL, the reinitializer +** is called when the content of a page in cache is restored to its original +** value as a result of a rollback. The callback gives higher-level code +** an opportunity to restore the EXTRA section to agree with the restored +** page data. +*/ +void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){ + pPager->xReiniter = xReinit; +} + +/* +** Set the page size to *pPageSize. If the suggest new page size is +** inappropriate, then an alternative page size is set to that +** value before returning. +*/ +int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){ + int rc = SQLITE_OK; + u16 pageSize = *pPageSize; + assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) ); + if( pageSize && pageSize!=pPager->pageSize + && !pPager->memDb && pPager->nRef==0 + ){ + char *pNew = (char *)sqlite3_malloc(pageSize); + if( !pNew ){ + rc = SQLITE_NOMEM; + }else{ + pagerEnter(pPager); + pager_reset(pPager); + pPager->pageSize = pageSize; + setSectorSize(pPager); + sqlite3_free(pPager->pTmpSpace); + pPager->pTmpSpace = pNew; + pagerLeave(pPager); + } + } + *pPageSize = pPager->pageSize; + return rc; +} + +/* +** Return a pointer to the "temporary page" buffer held internally +** by the pager. This is a buffer that is big enough to hold the +** entire content of a database page. This buffer is used internally +** during rollback and will be overwritten whenever a rollback +** occurs. But other modules are free to use it too, as long as +** no rollbacks are happening. +*/ +void *sqlite3PagerTempSpace(Pager *pPager){ + return pPager->pTmpSpace; +} + +/* +** Attempt to set the maximum database page count if mxPage is positive. +** Make no changes if mxPage is zero or negative. And never reduce the +** maximum page count below the current size of the database. +** +** Regardless of mxPage, return the current maximum page count. +*/ +int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ + if( mxPage>0 ){ + pPager->mxPgno = mxPage; + } + sqlite3PagerPagecount(pPager); + return pPager->mxPgno; +} + +/* +** The following set of routines are used to disable the simulated +** I/O error mechanism. These routines are used to avoid simulated +** errors in places where we do not care about errors. +** +** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops +** and generate no code. +*/ +#ifdef SQLITE_TEST +extern int sqlite3_io_error_pending; +extern int sqlite3_io_error_hit; +static int saved_cnt; +void disable_simulated_io_errors(void){ + saved_cnt = sqlite3_io_error_pending; + sqlite3_io_error_pending = -1; +} +void enable_simulated_io_errors(void){ + sqlite3_io_error_pending = saved_cnt; +} +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +/* +** Read the first N bytes from the beginning of the file into memory +** that pDest points to. +** +** No error checking is done. The rational for this is that this function +** may be called even if the file does not exist or contain a header. In +** these cases sqlite3OsRead() will return an error, to which the correct +** response is to zero the memory at pDest and continue. A real IO error +** will presumably recur and be picked up later (Todo: Think about this). +*/ +int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ + int rc = SQLITE_OK; + memset(pDest, 0, N); + assert(MEMDB||pPager->fd->pMethods||pPager->tempFile); + if( pPager->fd->pMethods ){ + IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) + rc = sqlite3OsRead(pPager->fd, pDest, N, 0); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + } + return rc; +} + +/* +** Return the total number of pages in the disk file associated with +** pPager. +** +** If the PENDING_BYTE lies on the page directly after the end of the +** file, then consider this page part of the file too. For example, if +** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the +** file is 4096 bytes, 5 is returned instead of 4. +*/ +int sqlite3PagerPagecount(Pager *pPager){ + i64 n = 0; + int rc; + assert( pPager!=0 ); + if( pPager->errCode ){ + return 0; + } + if( pPager->dbSize>=0 ){ + n = pPager->dbSize; + } else { + assert(pPager->fd->pMethods||pPager->tempFile); + if( (pPager->fd->pMethods) + && (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){ + pPager->nRef++; + pager_error(pPager, rc); + pPager->nRef--; + return 0; + } + if( n>0 && npageSize ){ + n = 1; + }else{ + n /= pPager->pageSize; + } + if( pPager->state!=PAGER_UNLOCK ){ + pPager->dbSize = n; + } + } + if( n==(PENDING_BYTE/pPager->pageSize) ){ + n++; + } + if( n>pPager->mxPgno ){ + pPager->mxPgno = n; + } + return n; +} + + +#ifndef SQLITE_OMIT_MEMORYDB +/* +** Clear a PgHistory block +*/ +static void clearHistory(PgHistory *pHist){ + sqlite3_free(pHist->pOrig); + sqlite3_free(pHist->pStmt); + pHist->pOrig = 0; + pHist->pStmt = 0; +} +#else +#define clearHistory(x) +#endif + +/* +** Forward declaration +*/ +static int syncJournal(Pager*); + +/* +** Unlink pPg from its hash chain. Also set the page number to 0 to indicate +** that the page is not part of any hash chain. This is required because the +** sqlite3PagerMovepage() routine can leave a page in the +** pNextFree/pPrevFree list that is not a part of any hash-chain. +*/ +static void unlinkHashChain(Pager *pPager, PgHdr *pPg){ + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + return; + } + if( pPg->pNextHash ){ + pPg->pNextHash->pPrevHash = pPg->pPrevHash; + } + if( pPg->pPrevHash ){ + assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg ); + pPg->pPrevHash->pNextHash = pPg->pNextHash; + }else{ + int h = pPg->pgno & (pPager->nHash-1); + pPager->aHash[h] = pPg->pNextHash; + } + if( MEMDB ){ + clearHistory(PGHDR_TO_HIST(pPg, pPager)); + } + pPg->pgno = 0; + pPg->pNextHash = pPg->pPrevHash = 0; +} + +/* +** Unlink a page from the free list (the list of all pages where nRef==0) +** and from its hash collision chain. +*/ +static void unlinkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + + /* Unlink from free page list */ + lruListRemove(pPg); + + /* Unlink from the pgno hash table */ + unlinkHashChain(pPager, pPg); +} + +/* +** This routine is used to truncate the cache when a database +** is truncated. Drop from the cache all pages whose pgno is +** larger than pPager->dbSize and is unreferenced. +** +** Referenced pages larger than pPager->dbSize are zeroed. +** +** Actually, at the point this routine is called, it would be +** an error to have a referenced page. But rather than delete +** that page and guarantee a subsequent segfault, it seems better +** to zero it and hope that we error out sanely. +*/ +static void pager_truncate_cache(Pager *pPager){ + PgHdr *pPg; + PgHdr **ppPg; + int dbSize = pPager->dbSize; + + ppPg = &pPager->pAll; + while( (pPg = *ppPg)!=0 ){ + if( pPg->pgno<=dbSize ){ + ppPg = &pPg->pNextAll; + }else if( pPg->nRef>0 ){ + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + ppPg = &pPg->pNextAll; + }else{ + *ppPg = pPg->pNextAll; + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + unlinkPage(pPg); + makeClean(pPg); + sqlite3_free(pPg); + pPager->nPage--; + } + } +} + +/* +** Try to obtain a lock on a file. Invoke the busy callback if the lock +** is currently not available. Repeat until the busy callback returns +** false or until the lock succeeds. +** +** Return SQLITE_OK on success and an error code if we cannot obtain +** the lock. +*/ +static int pager_wait_on_lock(Pager *pPager, int locktype){ + int rc; + + /* The OS lock values must be the same as the Pager lock values */ + assert( PAGER_SHARED==SHARED_LOCK ); + assert( PAGER_RESERVED==RESERVED_LOCK ); + assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); + + /* If the file is currently unlocked then the size must be unknown */ + assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB ); + + if( pPager->state>=locktype ){ + rc = SQLITE_OK; + }else{ + do { + rc = sqlite3OsLock(pPager->fd, locktype); + }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); + if( rc==SQLITE_OK ){ + pPager->state = locktype; + IOTRACE(("LOCK %p %d\n", pPager, locktype)) + } + } + return rc; +} + +/* +** Truncate the file to the number of pages specified. +*/ +int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){ + int rc; + assert( pPager->state>=PAGER_SHARED || MEMDB ); + sqlite3PagerPagecount(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; + return rc; + } + if( nPage>=(unsigned)pPager->dbSize ){ + return SQLITE_OK; + } + if( MEMDB ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + return SQLITE_OK; + } + pagerEnter(pPager); + rc = syncJournal(pPager); + pagerLeave(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Get an exclusive lock on the database before truncating. */ + pagerEnter(pPager); + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + pagerLeave(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + + rc = pager_truncate(pPager, nPage); + return rc; +} + +/* +** Shutdown the page cache. Free all memory and close all files. +** +** If a transaction was in progress when this routine is called, that +** transaction is rolled back. All outstanding pages are invalidated +** and their memory is freed. Any attempt to use a page associated +** with this page cache after this function returns will likely +** result in a coredump. +** +** This function always succeeds. If a transaction is active an attempt +** is made to roll it back. If an error occurs during the rollback +** a hot journal may be left in the filesystem but no error is returned +** to the caller. +*/ +int sqlite3PagerClose(Pager *pPager){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + if( !MEMDB ){ + sqlite3_mutex *mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + sqlite3_mutex_enter(mutex); + if( pPager->pPrev ){ + pPager->pPrev->pNext = pPager->pNext; + }else{ + sqlite3PagerList = pPager->pNext; + } + if( pPager->pNext ){ + pPager->pNext->pPrev = pPager->pPrev; + } + sqlite3_mutex_leave(mutex); + } +#endif + + disable_simulated_io_errors(); + pPager->errCode = 0; + pPager->exclusiveMode = 0; + pager_reset(pPager); + pagerUnlockAndRollback(pPager); + enable_simulated_io_errors(); + PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); + IOTRACE(("CLOSE %p\n", pPager)) + assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); + if( pPager->journalOpen ){ + sqlite3OsClose(pPager->jfd); + } + sqlite3_free(pPager->aInJournal); + if( pPager->stmtOpen ){ + sqlite3OsClose(pPager->stfd); + } + sqlite3OsClose(pPager->fd); + /* Temp files are automatically deleted by the OS + ** if( pPager->tempFile ){ + ** sqlite3OsDelete(pPager->zFilename); + ** } + */ + + sqlite3_free(pPager->aHash); + sqlite3_free(pPager->pTmpSpace); + sqlite3_free(pPager); + return SQLITE_OK; +} + +#if !defined(NDEBUG) || defined(SQLITE_TEST) +/* +** Return the page number for the given page data. +*/ +Pgno sqlite3PagerPagenumber(DbPage *p){ + return p->pgno; +} +#endif + +/* +** The page_ref() function increments the reference count for a page. +** If the page is currently on the freelist (the reference count is zero) then +** remove it from the freelist. +** +** For non-test systems, page_ref() is a macro that calls _page_ref() +** online of the reference count is zero. For test systems, page_ref() +** is a real function so that we can set breakpoints and trace it. +*/ +static void _page_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + /* The page is currently on the freelist. Remove it. */ + lruListRemove(pPg); + pPg->pPager->nRef++; + } + pPg->nRef++; +} +#ifdef SQLITE_DEBUG + static void page_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + _page_ref(pPg); + }else{ + pPg->nRef++; + } + } +#else +# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++) +#endif + +/* +** Increment the reference count for a page. The input pointer is +** a reference to the page data. +*/ +int sqlite3PagerRef(DbPage *pPg){ + pagerEnter(pPg->pPager); + page_ref(pPg); + pagerLeave(pPg->pPager); + return SQLITE_OK; +} + +/* +** Sync the journal. In other words, make sure all the pages that have +** been written to the journal have actually reached the surface of the +** disk. It is not safe to modify the original database file until after +** the journal has been synced. If the original database is modified before +** the journal is synced and a power failure occurs, the unsynced journal +** data would be lost and we would be unable to completely rollback the +** database changes. Database corruption would occur. +** +** This routine also updates the nRec field in the header of the journal. +** (See comments on the pager_playback() routine for additional information.) +** If the sync mode is FULL, two syncs will occur. First the whole journal +** is synced, then the nRec field is updated, then a second sync occurs. +** +** For temporary databases, we do not care if we are able to rollback +** after a power failure, so no sync occurs. +** +** If the IOCAP_SEQUENTIAL flag is set for the persistent media on which +** the database is stored, then OsSync() is never called on the journal +** file. In this case all that is required is to update the nRec field in +** the journal header. +** +** This routine clears the needSync field of every page current held in +** memory. +*/ +static int syncJournal(Pager *pPager){ + PgHdr *pPg; + int rc = SQLITE_OK; + + + /* Sync the journal before modifying the main database + ** (assuming there is a journal and it needs to be synced.) + */ + if( pPager->needSync ){ + if( !pPager->tempFile ){ + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + assert( pPager->journalOpen ); + + /* assert( !pPager->noSync ); // noSync might be set if synchronous + ** was turned off after the transaction was started. Ticket #615 */ +#ifndef NDEBUG + { + /* Make sure the pPager->nRec counter we are keeping agrees + ** with the nRec computed from the size of the journal file. + */ + i64 jSz; + rc = sqlite3OsFileSize(pPager->jfd, &jSz); + if( rc!=0 ) return rc; + assert( pPager->journalOff==jSz ); + } +#endif + if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ + /* Write the nRec value into the journal file header. If in + ** full-synchronous mode, sync the journal first. This ensures that + ** all data has really hit the disk before nRec is updated to mark + ** it as a candidate for rollback. + ** + ** This is not required if the persistent media supports the + ** SAFE_APPEND property. Because in this case it is not possible + ** for garbage data to be appended to the file, the nRec field + ** is populated with 0xFFFFFFFF when the journal header is written + ** and never needs to be updated. + */ + i64 jrnlOff; + if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags); + if( rc!=0 ) return rc; + } + + jrnlOff = pPager->journalHdr + sizeof(aJournalMagic); + IOTRACE(("JHDR %p %lld %d\n", pPager, jrnlOff, 4)); + rc = write32bits(pPager->jfd, jrnlOff, pPager->nRec); + if( rc ) return rc; + } + if( 0==(iDc&SQLITE_IOCAP_SEQUENTIAL) ){ + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->sync_flags| + (pPager->sync_flags==SQLITE_SYNC_FULL?SQLITE_SYNC_DATAONLY:0) + ); + if( rc!=0 ) return rc; + } + pPager->journalStarted = 1; + } + pPager->needSync = 0; + + /* Erase the needSync flag from every page. + */ + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + pPg->needSync = 0; + } + lruListSetFirstSynced(pPager); + } + +#ifndef NDEBUG + /* If the Pager.needSync flag is clear then the PgHdr.needSync + ** flag must also be clear for all pages. Verify that this + ** invariant is true. + */ + else{ + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + assert( pPg->needSync==0 ); + } + assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); + } +#endif + + return rc; +} + +/* +** Merge two lists of pages connected by pDirty and in pgno order. +** Do not both fixing the pPrevDirty pointers. +*/ +static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){ + PgHdr result, *pTail; + pTail = &result; + while( pA && pB ){ + if( pA->pgnopgno ){ + pTail->pDirty = pA; + pTail = pA; + pA = pA->pDirty; + }else{ + pTail->pDirty = pB; + pTail = pB; + pB = pB->pDirty; + } + } + if( pA ){ + pTail->pDirty = pA; + }else if( pB ){ + pTail->pDirty = pB; + }else{ + pTail->pDirty = 0; + } + return result.pDirty; +} + +/* +** Sort the list of pages in accending order by pgno. Pages are +** connected by pDirty pointers. The pPrevDirty pointers are +** corrupted by this sort. +*/ +#define N_SORT_BUCKET_ALLOC 25 +#define N_SORT_BUCKET 25 +#ifdef SQLITE_TEST + int sqlite3_pager_n_sort_bucket = 0; + #undef N_SORT_BUCKET + #define N_SORT_BUCKET \ + (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC) +#endif +static PgHdr *sort_pagelist(PgHdr *pIn){ + PgHdr *a[N_SORT_BUCKET_ALLOC], *p; + int i; + memset(a, 0, sizeof(a)); + while( pIn ){ + p = pIn; + pIn = p->pDirty; + p->pDirty = 0; + for(i=0; ipPager; + + /* At this point there may be either a RESERVED or EXCLUSIVE lock on the + ** database file. If there is already an EXCLUSIVE lock, the following + ** calls to sqlite3OsLock() are no-ops. + ** + ** Moving the lock from RESERVED to EXCLUSIVE actually involves going + ** through an intermediate state PENDING. A PENDING lock prevents new + ** readers from attaching to the database but is unsufficient for us to + ** write. The idea of a PENDING lock is to prevent new readers from + ** coming in while we wait for existing readers to clear. + ** + ** While the pager is in the RESERVED state, the original database file + ** is unchanged and we can rollback without having to playback the + ** journal into the original database file. Once we transition to + ** EXCLUSIVE, it means the database file has been changed and any rollback + ** will require a journal playback. + */ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } + + pList = sort_pagelist(pList); + for(p=pList; p; p=p->pDirty){ + assert( p->dirty ); + p->dirty = 0; + } + while( pList ){ + + /* If the file has not yet been opened, open it now. */ + if( !pPager->fd->pMethods ){ + assert(pPager->tempFile); + rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->fd, pPager->zFilename, + pPager->vfsFlags); + if( rc ) return rc; + } + + /* If there are dirty pages in the page cache with page numbers greater + ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to + ** make the file smaller (presumably by auto-vacuum code). Do not write + ** any such pages to the file. + */ + if( pList->pgno<=pPager->dbSize ){ + i64 offset = (pList->pgno-1)*(i64)pPager->pageSize; + char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); + PAGERTRACE4("STORE %d page %d hash(%08x)\n", + PAGERID(pPager), pList->pgno, pager_pagehash(pList)); + IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno)); + rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset); + PAGER_INCR(sqlite3_pager_writedb_count); + PAGER_INCR(pPager->nWrite); + if( pList->pgno==1 ){ + memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); + } + } +#ifndef NDEBUG + else{ + PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); + } +#endif + if( rc ) return rc; +#ifdef SQLITE_CHECK_PAGES + pList->pageHash = pager_pagehash(pList); +#endif + pList = pList->pDirty; + } + return SQLITE_OK; +} + +/* +** Collect every dirty page into a dirty list and +** return a pointer to the head of that list. All pages are +** collected even if they are still in use. +*/ +static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ + return pPager->pDirty; +} + +/* +** Return TRUE if there is a hot journal on the given pager. +** A hot journal is one that needs to be played back. +** +** If the current size of the database file is 0 but a journal file +** exists, that is probably an old journal left over from a prior +** database with the same name. Just delete the journal. +*/ +static int hasHotJournal(Pager *pPager){ + sqlite3_vfs *pVfs = pPager->pVfs; + if( !pPager->useJournal ) return 0; + if( !pPager->fd->pMethods ) return 0; + if( !sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){ + return 0; + } + if( sqlite3OsCheckReservedLock(pPager->fd) ){ + return 0; + } + if( sqlite3PagerPagecount(pPager)==0 ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + return 0; + }else{ + return 1; + } +} + +/* +** Try to find a page in the cache that can be recycled. +** +** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It +** does not set the pPager->errCode variable. +*/ +static int pager_recycle(Pager *pPager, PgHdr **ppPg){ + PgHdr *pPg; + *ppPg = 0; + + /* It is illegal to call this function unless the pager object + ** pointed to by pPager has at least one free page (page with nRef==0). + */ + assert(!MEMDB); + assert(pPager->lru.pFirst); + + /* Find a page to recycle. Try to locate a page that does not + ** require us to do an fsync() on the journal. + */ + pPg = pPager->lru.pFirstSynced; + + /* If we could not find a page that does not require an fsync() + ** on the journal file then fsync the journal file. This is a + ** very slow operation, so we work hard to avoid it. But sometimes + ** it can't be helped. + */ + if( pPg==0 && pPager->lru.pFirst){ + int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); + int rc = syncJournal(pPager); + if( rc!=0 ){ + return rc; + } + if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){ + /* If in full-sync mode, write a new journal header into the + ** journal file. This is done to avoid ever modifying a journal + ** header that is involved in the rollback of pages that have + ** already been written to the database (in case the header is + ** trashed when the nRec field is updated). + */ + pPager->nRec = 0; + assert( pPager->journalOff > 0 ); + assert( pPager->doNotSync==0 ); + rc = writeJournalHdr(pPager); + if( rc!=0 ){ + return rc; + } + } + pPg = pPager->lru.pFirst; + } + + assert( pPg->nRef==0 ); + + /* Write the page to the database file if it is dirty. + */ + if( pPg->dirty ){ + int rc; + assert( pPg->needSync==0 ); + makeClean(pPg); + pPg->dirty = 1; + pPg->pDirty = 0; + rc = pager_write_pagelist( pPg ); + pPg->dirty = 0; + if( rc!=SQLITE_OK ){ + return rc; + } + } + assert( pPg->dirty==0 ); + + /* If the page we are recycling is marked as alwaysRollback, then + ** set the global alwaysRollback flag, thus disabling the + ** sqlite3PagerDontRollback() optimization for the rest of this transaction. + ** It is necessary to do this because the page marked alwaysRollback + ** might be reloaded at a later time but at that point we won't remember + ** that is was marked alwaysRollback. This means that all pages must + ** be marked as alwaysRollback from here on out. + */ + if( pPg->alwaysRollback ){ + IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager)) + pPager->alwaysRollback = 1; + } + + /* Unlink the old page from the free list and the hash table + */ + unlinkPage(pPg); + assert( pPg->pgno==0 ); + + *ppPg = pPg; + return SQLITE_OK; +} + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* +** This function is called to free superfluous dynamically allocated memory +** held by the pager system. Memory in use by any SQLite pager allocated +** by the current thread may be sqlite3_free()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. The return value is the total number +** of bytes of memory released. +*/ +int sqlite3PagerReleaseMemory(int nReq){ + int nReleased = 0; /* Bytes of memory released so far */ + sqlite3_mutex *mutex; /* The MEM2 mutex */ + Pager *pPager; /* For looping over pagers */ + BusyHandler *savedBusy; /* Saved copy of the busy handler */ + int rc = SQLITE_OK; + + /* Acquire the memory-management mutex + */ + mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2); + sqlite3_mutex_enter(mutex); + + /* Signal all database connections that memory management wants + ** to have access to the pagers. + */ + for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){ + pPager->iInUseMM = 1; + } + + while( rc==SQLITE_OK && (nReq<0 || nReleasedneedSync || pPg->pPager->iInUseDB) ){ + pPg = pPg->gfree.pNext; + } + if( !pPg ){ + pPg = sqlite3LruPageList.pFirst; + while( pPg && pPg->pPager->iInUseDB ){ + pPg = pPg->gfree.pNext; + } + } + sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + + /* If pPg==0, then the block above has failed to find a page to + ** recycle. In this case return early - no further memory will + ** be released. + */ + if( !pPg ) break; + + pPager = pPg->pPager; + assert(!pPg->needSync || pPg==pPager->lru.pFirst); + assert(pPg->needSync || pPg==pPager->lru.pFirstSynced); + + savedBusy = pPager->pBusyHandler; + pPager->pBusyHandler = 0; + rc = pager_recycle(pPager, &pRecycled); + pPager->pBusyHandler = savedBusy; + assert(pRecycled==pPg || rc!=SQLITE_OK); + if( rc==SQLITE_OK ){ + /* We've found a page to free. At this point the page has been + ** removed from the page hash-table, free-list and synced-list + ** (pFirstSynced). It is still in the all pages (pAll) list. + ** Remove it from this list before freeing. + ** + ** Todo: Check the Pager.pStmt list to make sure this is Ok. It + ** probably is though. + */ + PgHdr *pTmp; + assert( pPg ); + if( pPg==pPager->pAll ){ + pPager->pAll = pPg->pNextAll; + }else{ + for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} + pTmp->pNextAll = pPg->pNextAll; + } + nReleased += ( + sizeof(*pPg) + pPager->pageSize + + sizeof(u32) + pPager->nExtra + + MEMDB*sizeof(PgHistory) + ); + IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + sqlite3_free(pPg); + pPager->nPage--; + }else{ + /* An error occured whilst writing to the database file or + ** journal in pager_recycle(). The error is not returned to the + ** caller of this function. Instead, set the Pager.errCode variable. + ** The error will be returned to the user (or users, in the case + ** of a shared pager cache) of the pager for which the error occured. + */ + assert( + (rc&0xff)==SQLITE_IOERR || + rc==SQLITE_FULL || + rc==SQLITE_BUSY + ); + assert( pPager->state>=PAGER_RESERVED ); + pager_error(pPager, rc); + } + } + + /* Clear the memory management flags and release the mutex + */ + for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){ + pPager->iInUseMM = 0; + } + sqlite3_mutex_leave(mutex); + + /* Return the number of bytes released + */ + return nReleased; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */ + +/* +** Read the content of page pPg out of the database file. +*/ +static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ + int rc; + i64 offset; + assert( MEMDB==0 ); + assert(pPager->fd->pMethods||pPager->tempFile); + if( !pPager->fd->pMethods ){ + return SQLITE_IOERR_SHORT_READ; + } + offset = (pgno-1)*(i64)pPager->pageSize; + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset); + PAGER_INCR(sqlite3_pager_readdb_count); + PAGER_INCR(pPager->nRead); + IOTRACE(("PGIN %p %d\n", pPager, pgno)); + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24], + sizeof(pPager->dbFileVers)); + } + CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + PAGERTRACE4("FETCH %d page %d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)); + return rc; +} + + +/* +** This function is called to obtain the shared lock required before +** data may be read from the pager cache. If the shared lock has already +** been obtained, this function is a no-op. +** +** Immediately after obtaining the shared lock (if required), this function +** checks for a hot-journal file. If one is found, an emergency rollback +** is performed immediately. +*/ +static int pagerSharedLock(Pager *pPager){ + int rc = SQLITE_OK; + int isHot = 0; + + /* If this database is opened for exclusive access, has no outstanding + ** page references and is in an error-state, now is the chance to clear + ** the error. Discard the contents of the pager-cache and treat any + ** open journal file as a hot-journal. + */ + if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){ + if( pPager->journalOpen ){ + isHot = 1; + } + pager_reset(pPager); + pPager->errCode = SQLITE_OK; + } + + /* If the pager is still in an error state, do not proceed. The error + ** state will be cleared at some point in the future when all page + ** references are dropped and the cache can be discarded. + */ + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return pPager->errCode; + } + + if( pPager->state==PAGER_UNLOCK || isHot ){ + sqlite3_vfs *pVfs = pPager->pVfs; + if( !MEMDB ){ + assert( pPager->nRef==0 ); + if( !pPager->noReadlock ){ + rc = pager_wait_on_lock(pPager, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + return pager_error(pPager, rc); + } + assert( pPager->state>=SHARED_LOCK ); + } + + /* If a journal file exists, and there is no RESERVED lock on the + ** database file, then it either needs to be played back or deleted. + */ + if( hasHotJournal(pPager) || isHot ){ + /* Get an EXCLUSIVE lock on the database file. At this point it is + ** important that a RESERVED lock is not obtained on the way to the + ** EXCLUSIVE lock. If it were, another process might open the + ** database file, detect the RESERVED lock, and conclude that the + ** database is safe to read while this process is still rolling it + ** back. + ** + ** Because the intermediate RESERVED lock is not requested, the + ** second process will get to this point in the code and fail to + ** obtain its own EXCLUSIVE lock on the database file. + */ + if( pPager->statefd, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + pager_unlock(pPager); + return pager_error(pPager, rc); + } + pPager->state = PAGER_EXCLUSIVE; + } + + /* Open the journal for reading only. Return SQLITE_BUSY if + ** we are unable to open the journal file. + ** + ** The journal file does not need to be locked itself. The + ** journal file is never open unless the main database file holds + ** a write lock, so there is never any chance of two or more + ** processes opening the journal at the same time. + ** + ** Open the journal for read/write access. This is because in + ** exclusive-access mode the file descriptor will be kept open and + ** possibly used for a transaction later on. On some systems, the + ** OsTruncate() call used in exclusive-access mode also requires + ** a read/write file handle. + */ + if( !isHot ){ + rc = SQLITE_BUSY; + if( sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS) ){ + int fout = 0; + int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL; + assert( !pPager->tempFile ); + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout); + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); + if( fout&SQLITE_OPEN_READONLY ){ + rc = SQLITE_BUSY; + sqlite3OsClose(pPager->jfd); + } + } + } + if( rc!=SQLITE_OK ){ + pager_unlock(pPager); + return ((rc==SQLITE_NOMEM||rc==SQLITE_IOERR_NOMEM)?rc:SQLITE_BUSY); + } + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + + /* Playback and delete the journal. Drop the database write + ** lock and reacquire the read lock. + */ + rc = pager_playback(pPager, 1); + if( rc!=SQLITE_OK ){ + return pager_error(pPager, rc); + } + assert(pPager->state==PAGER_SHARED || + (pPager->exclusiveMode && pPager->state>PAGER_SHARED) + ); + } + + if( pPager->pAll ){ + /* The shared-lock has just been acquired on the database file + ** and there are already pages in the cache (from a previous + ** read or write transaction). Check to see if the database + ** has been modified. If the database has changed, flush the + ** cache. + ** + ** Database changes is detected by looking at 15 bytes beginning + ** at offset 24 into the file. The first 4 of these 16 bytes are + ** a 32-bit counter that is incremented with each change. The + ** other bytes change randomly with each file change when + ** a codec is in use. + ** + ** There is a vanishingly small chance that a change will not be + ** detected. The chance of an undetected change is so small that + ** it can be neglected. + */ + char dbFileVers[sizeof(pPager->dbFileVers)]; + sqlite3PagerPagecount(pPager); + + if( pPager->errCode ){ + return pPager->errCode; + } + + if( pPager->dbSize>0 ){ + IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); + rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + memset(dbFileVers, 0, sizeof(dbFileVers)); + } + + if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ + pager_reset(pPager); + } + } + } + assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED ); + if( pPager->state==PAGER_UNLOCK ){ + pPager->state = PAGER_SHARED; + } + } + + return rc; +} + +/* +** Allocate a PgHdr object. Either create a new one or reuse +** an existing one that is not otherwise in use. +** +** A new PgHdr structure is created if any of the following are +** true: +** +** (1) We have not exceeded our maximum allocated cache size +** as set by the "PRAGMA cache_size" command. +** +** (2) There are no unused PgHdr objects available at this time. +** +** (3) This is an in-memory database. +** +** (4) There are no PgHdr objects that do not require a journal +** file sync and a sync of the journal file is currently +** prohibited. +** +** Otherwise, reuse an existing PgHdr. In other words, reuse an +** existing PgHdr if all of the following are true: +** +** (1) We have reached or exceeded the maximum cache size +** allowed by "PRAGMA cache_size". +** +** (2) There is a PgHdr available with PgHdr->nRef==0 +** +** (3) We are not in an in-memory database +** +** (4) Either there is an available PgHdr that does not need +** to be synced to disk or else disk syncing is currently +** allowed. +*/ +static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){ + int rc = SQLITE_OK; + PgHdr *pPg; + int nByteHdr; + + /* Create a new PgHdr if any of the four conditions defined + ** above are met: */ + if( pPager->nPagemxPage + || pPager->lru.pFirst==0 + || MEMDB + || (pPager->lru.pFirstSynced==0 && pPager->doNotSync) + ){ + if( pPager->nPage>=pPager->nHash ){ + pager_resize_hash_table(pPager, + pPager->nHash<256 ? 256 : pPager->nHash*2); + if( pPager->nHash==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + } + pagerLeave(pPager); + nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra + + MEMDB*sizeof(PgHistory); + pPg = sqlite3_malloc( nByteHdr + pPager->pageSize ); + pagerEnter(pPager); + if( pPg==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + memset(pPg, 0, nByteHdr); + pPg->pData = (void*)(nByteHdr + (char*)pPg); + pPg->pPager = pPager; + pPg->pNextAll = pPager->pAll; + pPager->pAll = pPg; + pPager->nPage++; + }else{ + /* Recycle an existing page with a zero ref-count. */ + rc = pager_recycle(pPager, &pPg); + if( rc==SQLITE_BUSY ){ + rc = SQLITE_IOERR_BLOCKED; + } + if( rc!=SQLITE_OK ){ + goto pager_allocate_out; + } + assert( pPager->state>=SHARED_LOCK ); + assert(pPg); + } + *ppPg = pPg; + +pager_allocate_out: + return rc; +} + +/* +** Make sure we have the content for a page. If the page was +** previously acquired with noContent==1, then the content was +** just initialized to zeros instead of being read from disk. +** But now we need the real data off of disk. So make sure we +** have it. Read it in if we do not have it already. +*/ +static int pager_get_content(PgHdr *pPg){ + if( pPg->needRead ){ + int rc = readDbPage(pPg->pPager, pPg, pPg->pgno); + if( rc==SQLITE_OK ){ + pPg->needRead = 0; + }else{ + return rc; + } + } + return SQLITE_OK; +} + +/* +** Acquire a page. +** +** A read lock on the disk file is obtained when the first page is acquired. +** This read lock is dropped when the last page is released. +** +** This routine works for any page number greater than 0. If the database +** file is smaller than the requested page, then no actual disk +** read occurs and the memory image of the page is initialized to +** all zeros. The extra data appended to a page is always initialized +** to zeros the first time a page is loaded into memory. +** +** The acquisition might fail for several reasons. In all cases, +** an appropriate error code is returned and *ppPage is set to NULL. +** +** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt +** to find a page in the in-memory cache first. If the page is not already +** in memory, this routine goes to disk to read it in whereas Lookup() +** just returns 0. This routine acquires a read-lock the first time it +** has to go to disk, and could also playback an old journal if necessary. +** Since Lookup() never goes to disk, it never has to deal with locks +** or journal files. +** +** If noContent is false, the page contents are actually read from disk. +** If noContent is true, it means that we do not care about the contents +** of the page at this time, so do not do a disk read. Just fill in the +** page content with zeros. But mark the fact that we have not read the +** content by setting the PgHdr.needRead flag. Later on, if +** sqlite3PagerWrite() is called on this page or if this routine is +** called again with noContent==0, that means that the content is needed +** and the disk read should occur at that point. +*/ +static int pagerAcquire( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int noContent /* Do not bother reading content from disk if true */ +){ + PgHdr *pPg; + int rc; + + assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 ); + + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page + ** number greater than this, or zero, is requested. + */ + if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + /* Make sure we have not hit any critical errors. + */ + assert( pPager!=0 ); + *ppPage = 0; + + /* If this is the first page accessed, then get a SHARED lock + ** on the database file. pagerSharedLock() is a no-op if + ** a database lock is already held. + */ + rc = pagerSharedLock(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state!=PAGER_UNLOCK ); + + pPg = pager_lookup(pPager, pgno); + if( pPg==0 ){ + /* The requested page is not in the page cache. */ + int nMax; + int h; + PAGER_INCR(pPager->nMiss); + rc = pagerAllocatePage(pPager, &pPg); + if( rc!=SQLITE_OK ){ + return rc; + } + + pPg->pgno = pgno; + assert( !MEMDB || pgno>pPager->stmtSize ); + if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ +#if 0 + sqlite3CheckMemory(pPager->aInJournal, pgno/8); +#endif + assert( pPager->journalOpen ); + pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; + pPg->needSync = 0; + }else{ + pPg->inJournal = 0; + pPg->needSync = 0; + } + + makeClean(pPg); + pPg->nRef = 1; + + pPager->nRef++; + if( pPager->nExtra>0 ){ + memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); + } + nMax = sqlite3PagerPagecount(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; + sqlite3PagerUnref(pPg); + return rc; + } + + /* Populate the page with data, either by reading from the database + ** file, or by setting the entire page to zero. + */ + if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){ + if( pgno>pPager->mxPgno ){ + sqlite3PagerUnref(pPg); + return SQLITE_FULL; + } + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + pPg->needRead = noContent && !pPager->alwaysRollback; + IOTRACE(("ZERO %p %d\n", pPager, pgno)); + }else{ + rc = readDbPage(pPager, pPg, pgno); + if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + pPg->pgno = 0; + sqlite3PagerUnref(pPg); + return rc; + } + pPg->needRead = 0; + } + + /* Link the page into the page hash table */ + h = pgno & (pPager->nHash-1); + assert( pgno!=0 ); + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + if( pPg->pNextHash ){ + assert( pPg->pNextHash->pPrevHash==0 ); + pPg->pNextHash->pPrevHash = pPg; + } + +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + }else{ + /* The requested page is in the page cache. */ + assert(pPager->nRef>0 || pgno==1); + PAGER_INCR(pPager->nHit); + if( !noContent ){ + rc = pager_get_content(pPg); + if( rc ){ + return rc; + } + } + page_ref(pPg); + } + *ppPage = pPg; + return SQLITE_OK; +} +int sqlite3PagerAcquire( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int noContent /* Do not bother reading content from disk if true */ +){ + int rc; + pagerEnter(pPager); + rc = pagerAcquire(pPager, pgno, ppPage, noContent); + pagerLeave(pPager); + return rc; +} + + +/* +** Acquire a page if it is already in the in-memory cache. Do +** not read the page from disk. Return a pointer to the page, +** or 0 if the page is not in cache. +** +** See also sqlite3PagerGet(). The difference between this routine +** and sqlite3PagerGet() is that _get() will go to the disk and read +** in the page if the page is not already in cache. This routine +** returns NULL if the page is not in cache or if a disk I/O error +** has ever happened. +*/ +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ + PgHdr *pPg = 0; + + assert( pPager!=0 ); + assert( pgno!=0 ); + + pagerEnter(pPager); + if( pPager->state==PAGER_UNLOCK ){ + assert( !pPager->pAll || pPager->exclusiveMode ); + }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + /* Do nothing */ + }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){ + page_ref(pPg); + } + pagerLeave(pPager); + return pPg; +} + +/* +** Release a page. +** +** If the number of references to the page drop to zero, then the +** page is added to the LRU list. When all references to all pages +** are released, a rollback occurs and the lock on the database is +** removed. +*/ +int sqlite3PagerUnref(DbPage *pPg){ + Pager *pPager = pPg->pPager; + + /* Decrement the reference count for this page + */ + assert( pPg->nRef>0 ); + pagerEnter(pPg->pPager); + pPg->nRef--; + + CHECK_PAGE(pPg); + + /* When the number of references to a page reach 0, call the + ** destructor and add the page to the freelist. + */ + if( pPg->nRef==0 ){ + + lruListAdd(pPg); + if( pPager->xDestructor ){ + pPager->xDestructor(pPg, pPager->pageSize); + } + + /* When all pages reach the freelist, drop the read lock from + ** the database file. + */ + pPager->nRef--; + assert( pPager->nRef>=0 ); + if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){ + pagerUnlockAndRollback(pPager); + } + } + pagerLeave(pPager); + return SQLITE_OK; +} + +/* +** Create a journal file for pPager. There should already be a RESERVED +** or EXCLUSIVE lock on the database file when this routine is called. +** +** Return SQLITE_OK if everything. Return an error code and release the +** write lock if anything goes wrong. +*/ +static int pager_open_journal(Pager *pPager){ + sqlite3_vfs *pVfs = pPager->pVfs; + int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE); + + int rc; + assert( !MEMDB ); + assert( pPager->state>=PAGER_RESERVED ); + assert( pPager->journalOpen==0 ); + assert( pPager->useJournal ); + assert( pPager->aInJournal==0 ); + sqlite3PagerPagecount(pPager); + pagerLeave(pPager); + pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 ); + pagerEnter(pPager); + if( pPager->aInJournal==0 ){ + rc = SQLITE_NOMEM; + goto failed_to_open_journal; + } + + if( pPager->tempFile ){ + flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL); + }else{ + flags |= (SQLITE_OPEN_MAIN_JOURNAL); + } +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + rc = sqlite3JournalOpen( + pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager) + ); +#else + rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0); +#endif + assert( rc!=SQLITE_OK || pPager->jfd->pMethods ); + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OsDelete(pVfs, pPager->zJournal, 0); + } + goto failed_to_open_journal; + } + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->needSync = 0; + pPager->alwaysRollback = 0; + pPager->nRec = 0; + if( pPager->errCode ){ + rc = pPager->errCode; + goto failed_to_open_journal; + } + pPager->origDbSize = pPager->dbSize; + + rc = writeJournalHdr(pPager); + + if( pPager->stmtAutoopen && rc==SQLITE_OK ){ + rc = sqlite3PagerStmtBegin(pPager); + } + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_NOMEM ){ + rc = pager_end_transaction(pPager); + if( rc==SQLITE_OK ){ + rc = SQLITE_FULL; + } + } + return rc; + +failed_to_open_journal: + sqlite3_free(pPager->aInJournal); + pPager->aInJournal = 0; + return rc; +} + +/* +** Acquire a write-lock on the database. The lock is removed when +** the any of the following happen: +** +** * sqlite3PagerCommitPhaseTwo() is called. +** * sqlite3PagerRollback() is called. +** * sqlite3PagerClose() is called. +** * sqlite3PagerUnref() is called to on every outstanding page. +** +** The first parameter to this routine is a pointer to any open page of the +** database file. Nothing changes about the page - it is used merely to +** acquire a pointer to the Pager structure and as proof that there is +** already a read-lock on the database. +** +** The second parameter indicates how much space in bytes to reserve for a +** master journal file-name at the start of the journal when it is created. +** +** A journal file is opened if this is not a temporary file. For temporary +** files, the opening of the journal file is deferred until there is an +** actual need to write to the journal. +** +** If the database is already reserved for writing, this routine is a no-op. +** +** If exFlag is true, go ahead and get an EXCLUSIVE lock on the file +** immediately instead of waiting until we try to flush the cache. The +** exFlag is ignored if a transaction is already active. +*/ +int sqlite3PagerBegin(DbPage *pPg, int exFlag){ + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + pagerEnter(pPager); + assert( pPg->nRef>0 ); + assert( pPager->state!=PAGER_UNLOCK ); + if( pPager->state==PAGER_SHARED ){ + assert( pPager->aInJournal==0 ); + if( MEMDB ){ + pPager->state = PAGER_EXCLUSIVE; + pPager->origDbSize = pPager->dbSize; + }else{ + rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); + if( rc==SQLITE_OK ){ + pPager->state = PAGER_RESERVED; + if( exFlag ){ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + } + } + if( rc!=SQLITE_OK ){ + pagerLeave(pPager); + return rc; + } + pPager->dirtyCache = 0; + PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); + if( pPager->useJournal && !pPager->tempFile ){ + rc = pager_open_journal(pPager); + } + } + }else if( pPager->journalOpen && pPager->journalOff==0 ){ + /* This happens when the pager was in exclusive-access mode last + ** time a (read or write) transaction was successfully concluded + ** by this connection. Instead of deleting the journal file it was + ** kept open and truncated to 0 bytes. + */ + assert( pPager->nRec==0 ); + assert( pPager->origDbSize==0 ); + assert( pPager->aInJournal==0 ); + sqlite3PagerPagecount(pPager); + pagerLeave(pPager); + pPager->aInJournal = sqlite3MallocZero( pPager->dbSize/8 + 1 ); + pagerEnter(pPager); + if( !pPager->aInJournal ){ + rc = SQLITE_NOMEM; + }else{ + pPager->origDbSize = pPager->dbSize; + rc = writeJournalHdr(pPager); + } + } + assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); + pagerLeave(pPager); + return rc; +} + +/* +** Make a page dirty. Set its dirty flag and add it to the dirty +** page list. +*/ +static void makeDirty(PgHdr *pPg){ + if( pPg->dirty==0 ){ + Pager *pPager = pPg->pPager; + pPg->dirty = 1; + pPg->pDirty = pPager->pDirty; + if( pPager->pDirty ){ + pPager->pDirty->pPrevDirty = pPg; + } + pPg->pPrevDirty = 0; + pPager->pDirty = pPg; + } +} + +/* +** Make a page clean. Clear its dirty bit and remove it from the +** dirty page list. +*/ +static void makeClean(PgHdr *pPg){ + if( pPg->dirty ){ + pPg->dirty = 0; + if( pPg->pDirty ){ + assert( pPg->pDirty->pPrevDirty==pPg ); + pPg->pDirty->pPrevDirty = pPg->pPrevDirty; + } + if( pPg->pPrevDirty ){ + assert( pPg->pPrevDirty->pDirty==pPg ); + pPg->pPrevDirty->pDirty = pPg->pDirty; + }else{ + assert( pPg->pPager->pDirty==pPg ); + pPg->pPager->pDirty = pPg->pDirty; + } + } +} + + +/* +** Mark a data page as writeable. The page is written into the journal +** if it is not there already. This routine must be called before making +** changes to a page. +** +** The first time this routine is called, the pager creates a new +** journal and acquires a RESERVED lock on the database. If the RESERVED +** lock could not be acquired, this routine returns SQLITE_BUSY. The +** calling routine must check for that return value and be careful not to +** change any page data until this routine returns SQLITE_OK. +** +** If the journal file could not be written because the disk is full, +** then this routine returns SQLITE_FULL and does an immediate rollback. +** All subsequent write attempts also return SQLITE_FULL until there +** is a call to sqlite3PagerCommit() or sqlite3PagerRollback() to +** reset. +*/ +static int pager_write(PgHdr *pPg){ + void *pData = PGHDR_TO_DATA(pPg); + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + + /* Check for errors + */ + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->readOnly ){ + return SQLITE_PERM; + } + + assert( !pPager->setMaster ); + + CHECK_PAGE(pPg); + + /* If this page was previously acquired with noContent==1, that means + ** we didn't really read in the content of the page. This can happen + ** (for example) when the page is being moved to the freelist. But + ** now we are (perhaps) moving the page off of the freelist for + ** reuse and we need to know its original content so that content + ** can be stored in the rollback journal. So do the read at this + ** time. + */ + rc = pager_get_content(pPg); + if( rc ){ + return rc; + } + + /* Mark the page as dirty. If the page has already been written + ** to the journal then we can return right away. + */ + makeDirty(pPg); + if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){ + pPager->dirtyCache = 1; + }else{ + + /* If we get this far, it means that the page needs to be + ** written to the transaction journal or the ckeckpoint journal + ** or both. + ** + ** First check to see that the transaction journal exists and + ** create it if it does not. + */ + assert( pPager->state!=PAGER_UNLOCK ); + rc = sqlite3PagerBegin(pPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state>=PAGER_RESERVED ); + if( !pPager->journalOpen && pPager->useJournal ){ + rc = pager_open_journal(pPager); + if( rc!=SQLITE_OK ) return rc; + } + assert( pPager->journalOpen || !pPager->useJournal ); + pPager->dirtyCache = 1; + + /* The transaction journal now exists and we have a RESERVED or an + ** EXCLUSIVE lock on the main database file. Write the current page to + ** the transaction journal if it is not there already. + */ + if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ + if( (int)pPg->pgno <= pPager->origDbSize ){ + if( MEMDB ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + assert( pHist->pOrig==0 ); + pHist->pOrig = sqlite3_malloc( pPager->pageSize ); + if( !pHist->pOrig ){ + return SQLITE_NOMEM; + } + memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); + }else{ + u32 cksum; + char *pData2; + + /* We should never write to the journal file the page that + ** contains the database locks. The following assert verifies + ** that we do not. */ + assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); + pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + cksum = pager_cksum(pPager, (u8*)pData2); + rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, + pPager->journalOff + 4); + pPager->journalOff += pPager->pageSize+4; + } + if( rc==SQLITE_OK ){ + rc = write32bits(pPager->jfd, pPager->journalOff, cksum); + pPager->journalOff += 4; + } + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + pPager->journalOff, pPager->pageSize)); + PAGER_INCR(sqlite3_pager_writej_count); + PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, pPg->needSync, pager_pagehash(pPg)); + + /* An error has occured writing to the journal file. The + ** transaction will be rolled back by the layer above. + */ + if( rc!=SQLITE_OK ){ + return rc; + } + + pPager->nRec++; + assert( pPager->aInJournal!=0 ); + pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); + pPg->needSync = !pPager->noSync; + if( pPager->stmtInUse ){ + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } + } + }else{ + pPg->needSync = !pPager->journalStarted && !pPager->noSync; + PAGERTRACE4("APPEND %d page %d needSync=%d\n", + PAGERID(pPager), pPg->pgno, pPg->needSync); + } + if( pPg->needSync ){ + pPager->needSync = 1; + } + pPg->inJournal = 1; + } + + /* If the statement journal is open and the page is not in it, + ** then write the current page to the statement journal. Note that + ** the statement journal format differs from the standard journal format + ** in that it omits the checksums and the header. + */ + if( pPager->stmtInUse + && !pageInStatement(pPg) + && (int)pPg->pgno<=pPager->stmtSize + ){ + assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); + if( MEMDB ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( pHist->pStmt==0 ); + pHist->pStmt = sqlite3_malloc( pPager->pageSize ); + if( pHist->pStmt ){ + memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); + } + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + page_add_to_stmt_list(pPg); + }else{ + i64 offset = pPager->stmtNRec*(4+pPager->pageSize); + char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + rc = write32bits(pPager->stfd, offset, pPg->pgno); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4); + } + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + if( rc!=SQLITE_OK ){ + return rc; + } + pPager->stmtNRec++; + assert( pPager->aInStmt!=0 ); + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } + } + } + + /* Update the database size and return. + */ + assert( pPager->state>=PAGER_SHARED ); + if( pPager->dbSize<(int)pPg->pgno ){ + pPager->dbSize = pPg->pgno; + if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ + pPager->dbSize++; + } + } + return rc; +} + +/* +** This function is used to mark a data-page as writable. It uses +** pager_write() to open a journal file (if it is not already open) +** and write the page *pData to the journal. +** +** The difference between this function and pager_write() is that this +** function also deals with the special case where 2 or more pages +** fit on a single disk sector. In this case all co-resident pages +** must have been written to the journal file before returning. +*/ +int sqlite3PagerWrite(DbPage *pDbPage){ + int rc = SQLITE_OK; + + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + pagerEnter(pPager); + if( !MEMDB && nPagePerSector>1 ){ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage; /* Number of pages starting at pg1 to journal */ + int ii; + int needSync = 0; + + /* Set the doNotSync flag to 1. This is because we cannot allow a journal + ** header to be written between the pages journaled by this function. + */ + assert( pPager->doNotSync==0 ); + pPager->doNotSync = 1; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = sqlite3PagerPagecount(pPager); + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iiaInJournal || pg==pPg->pgno || + pg>pPager->origDbSize || !(pPager->aInJournal[pg/8]&(1<<(pg&7))) + ) { + if( pg!=PAGER_MJ_PGNO(pPager) ){ + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + if( pPage->needSync ){ + needSync = 1; + } + sqlite3PagerUnref(pPage); + } + } + }else if( (pPage = pager_lookup(pPager, pg)) ){ + if( pPage->needSync ){ + needSync = 1; + } + } + } + + /* If the PgHdr.needSync flag is set for any of the nPage pages + ** starting at pg1, then it needs to be set for all of them. Because + ** writing to any of these nPage pages may damage the others, the + ** journal file must contain sync()ed copies of all of them + ** before any of them can be written out to the database file. + */ + if( needSync ){ + for(ii=0; iineedSync = 1; + } + assert(pPager->needSync); + } + + assert( pPager->doNotSync==1 ); + pPager->doNotSync = 0; + }else{ + rc = pager_write(pDbPage); + } + pagerLeave(pPager); + return rc; +} + +/* +** Return TRUE if the page given in the argument was previously passed +** to sqlite3PagerWrite(). In other words, return TRUE if it is ok +** to change the content of the page. +*/ +#ifndef NDEBUG +int sqlite3PagerIswriteable(DbPage *pPg){ + return pPg->dirty; +} +#endif + +#ifndef SQLITE_OMIT_VACUUM +/* +** Replace the content of a single page with the information in the third +** argument. +*/ +int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){ + PgHdr *pPg; + int rc; + + pagerEnter(pPager); + rc = sqlite3PagerGet(pPager, pgno, &pPg); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pPg); + if( rc==SQLITE_OK ){ + memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize); + } + sqlite3PagerUnref(pPg); + } + pagerLeave(pPager); + return rc; +} +#endif + +/* +** A call to this routine tells the pager that it is not necessary to +** write the information on page pPg back to the disk, even though +** that page might be marked as dirty. +** +** The overlying software layer calls this routine when all of the data +** on the given page is unused. The pager marks the page as clean so +** that it does not get written to disk. +** +** Tests show that this optimization, together with the +** sqlite3PagerDontRollback() below, more than double the speed +** of large INSERT operations and quadruple the speed of large DELETEs. +** +** When this routine is called, set the alwaysRollback flag to true. +** Subsequent calls to sqlite3PagerDontRollback() for the same page +** will thereafter be ignored. This is necessary to avoid a problem +** where a page with data is added to the freelist during one part of +** a transaction then removed from the freelist during a later part +** of the same transaction and reused for some other purpose. When it +** is first added to the freelist, this routine is called. When reused, +** the sqlite3PagerDontRollback() routine is called. But because the +** page contains critical data, we still need to be sure it gets +** rolled back in spite of the sqlite3PagerDontRollback() call. +*/ +void sqlite3PagerDontWrite(DbPage *pDbPage){ + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + + if( MEMDB ) return; + pagerEnter(pPager); + pPg->alwaysRollback = 1; + if( pPg->dirty && !pPager->stmtInUse ){ + assert( pPager->state>=PAGER_SHARED ); + if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ + /* If this pages is the last page in the file and the file has grown + ** during the current transaction, then do NOT mark the page as clean. + ** When the database file grows, we must make sure that the last page + ** gets written at least once so that the disk file will be the correct + ** size. If you do not write this page and the size of the file + ** on the disk ends up being too small, that can lead to database + ** corruption during the next transaction. + */ + }else{ + PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) + makeClean(pPg); +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + } + } + pagerLeave(pPager); +} + +/* +** A call to this routine tells the pager that if a rollback occurs, +** it is not necessary to restore the data on the given page. This +** means that the pager does not have to record the given page in the +** rollback journal. +** +** If we have not yet actually read the content of this page (if +** the PgHdr.needRead flag is set) then this routine acts as a promise +** that we will never need to read the page content in the future. +** so the needRead flag can be cleared at this point. +** +** This routine is only called from a single place in the sqlite btree +** code (when a leaf is removed from the free-list). This allows the +** following assumptions to be made about pPg: +** +** 1. PagerDontWrite() has been called on the page, OR +** PagerWrite() has not yet been called on the page. +** +** 2. The page existed when the transaction was started. +** +** Details: DontRollback() (this routine) is only called when a leaf is +** removed from the free list. DontWrite() is called whenever a page +** becomes a free-list leaf. +*/ +void sqlite3PagerDontRollback(DbPage *pPg){ + Pager *pPager = pPg->pPager; + + pagerEnter(pPager); + assert( pPager->state>=PAGER_RESERVED ); + + /* If the journal file is not open, or DontWrite() has been called on + ** this page (DontWrite() sets the alwaysRollback flag), then this + ** function is a no-op. + */ + if( pPager->journalOpen==0 || pPg->alwaysRollback || pPager->alwaysRollback ){ + pagerLeave(pPager); + return; + } + assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */ + + /* Check that PagerWrite() has not yet been called on this page, and + ** that the page existed when the transaction started. + */ + assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); + + assert( pPager->aInJournal!=0 ); + pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); + pPg->inJournal = 1; + pPg->needRead = 0; + if( pPager->stmtInUse ){ + assert( pPager->stmtSize <= pPager->origDbSize ); + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } + PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno)) + pagerLeave(pPager); +} + + +/* +** This routine is called to increment the database file change-counter, +** stored at byte 24 of the pager file. +*/ +static int pager_incr_changecounter(Pager *pPager, int isDirect){ + PgHdr *pPgHdr; + u32 change_counter; + int rc = SQLITE_OK; + + if( !pPager->changeCountDone ){ + /* Open page 1 of the file for writing. */ + rc = sqlite3PagerGet(pPager, 1, &pPgHdr); + if( rc!=SQLITE_OK ) return rc; + + if( !isDirect ){ + rc = sqlite3PagerWrite(pPgHdr); + if( rc!=SQLITE_OK ){ + sqlite3PagerUnref(pPgHdr); + return rc; + } + } + + /* Increment the value just read and write it back to byte 24. */ + change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers); + change_counter++; + put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); + + if( isDirect && pPager->fd->pMethods ){ + const void *zBuf = PGHDR_TO_DATA(pPgHdr); + rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); + } + + /* Release the page reference. */ + sqlite3PagerUnref(pPgHdr); + pPager->changeCountDone = 1; + } + return rc; +} + +/* +** Sync the database file for the pager pPager. zMaster points to the name +** of a master journal file that should be written into the individual +** journal file. zMaster may be NULL, which is interpreted as no master +** journal (a single database transaction). +** +** This routine ensures that the journal is synced, all dirty pages written +** to the database file and the database file synced. The only thing that +** remains to commit the transaction is to delete the journal file (or +** master journal file if specified). +** +** Note that if zMaster==NULL, this does not overwrite a previous value +** passed to an sqlite3PagerCommitPhaseOne() call. +** +** If parameter nTrunc is non-zero, then the pager file is truncated to +** nTrunc pages (this is used by auto-vacuum databases). +*/ +int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ + int rc = SQLITE_OK; + + PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", + pPager->zFilename, zMaster, nTrunc); + pagerEnter(pPager); + + /* If this is an in-memory db, or no pages have been written to, or this + ** function has already been called, it is a no-op. + */ + if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ + PgHdr *pPg; + +#ifdef SQLITE_ENABLE_ATOMIC_WRITE + /* The atomic-write optimization can be used if all of the + ** following are true: + ** + ** + The file-system supports the atomic-write property for + ** blocks of size page-size, and + ** + This commit is not part of a multi-file transaction, and + ** + Exactly one page has been modified and store in the journal file. + ** + ** If the optimization can be used, then the journal file will never + ** be created for this transaction. + */ + int useAtomicWrite = ( + !zMaster && + pPager->journalOff==jrnlBufferSize(pPager) && + nTrunc==0 && + (0==pPager->pDirty || 0==pPager->pDirty->pDirty) + ); + if( useAtomicWrite ){ + /* Update the nRec field in the journal file. */ + int offset = pPager->journalHdr + sizeof(aJournalMagic); + assert(pPager->nRec==1); + rc = write32bits(pPager->jfd, offset, pPager->nRec); + + /* Update the db file change counter. The following call will modify + ** the in-memory representation of page 1 to include the updated + ** change counter and then write page 1 directly to the database + ** file. Because of the atomic-write property of the host file-system, + ** this is safe. + */ + if( rc==SQLITE_OK ){ + rc = pager_incr_changecounter(pPager, 1); + } + }else{ + rc = sqlite3JournalCreate(pPager->jfd); + } + + if( !useAtomicWrite && rc==SQLITE_OK ) +#endif + + /* If a master journal file name has already been written to the + ** journal file, then no sync is required. This happens when it is + ** written, then the process fails to upgrade from a RESERVED to an + ** EXCLUSIVE lock. The next time the process tries to commit the + ** transaction the m-j name will have already been written. + */ + if( !pPager->setMaster ){ + assert( pPager->journalOpen ); + rc = pager_incr_changecounter(pPager, 0); + if( rc!=SQLITE_OK ) goto sync_exit; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + /* If this transaction has made the database smaller, then all pages + ** being discarded by the truncation must be written to the journal + ** file. + */ + Pgno i; + int iSkip = PAGER_MJ_PGNO(pPager); + for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ + if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){ + rc = sqlite3PagerGet(pPager, i, &pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = sqlite3PagerWrite(pPg); + sqlite3PagerUnref(pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + } + } + } +#endif + rc = writeMasterJournal(pPager, zMaster); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = syncJournal(pPager); + } + if( rc!=SQLITE_OK ) goto sync_exit; + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + if( rc!=SQLITE_OK ) goto sync_exit; + } +#endif + + /* Write all dirty pages to the database file */ + pPg = pager_get_all_dirty_pages(pPager); + rc = pager_write_pagelist(pPg); + if( rc!=SQLITE_OK ){ + while( pPg && !pPg->dirty ){ pPg = pPg->pDirty; } + pPager->pDirty = pPg; + goto sync_exit; + } + pPager->pDirty = 0; + + /* Sync the database file. */ + if( !pPager->noSync ){ + rc = sqlite3OsSync(pPager->fd, pPager->sync_flags); + } + IOTRACE(("DBSYNC %p\n", pPager)) + + pPager->state = PAGER_SYNCED; + }else if( MEMDB && nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + } + +sync_exit: + if( rc==SQLITE_IOERR_BLOCKED ){ + /* pager_incr_changecounter() may attempt to obtain an exclusive + * lock to spill the cache and return IOERR_BLOCKED. But since + * there is no chance the cache is inconsistent, it is + * better to return SQLITE_BUSY. + */ + rc = SQLITE_BUSY; + } + pagerLeave(pPager); + return rc; +} + + +/* +** Commit all changes to the database and release the write lock. +** +** If the commit fails for any reason, a rollback attempt is made +** and an error code is returned. If the commit worked, SQLITE_OK +** is returned. +*/ +int sqlite3PagerCommitPhaseTwo(Pager *pPager){ + int rc; + PgHdr *pPg; + + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->statedirty = 0; + pPg->inJournal = 0; + pHist->inStmt = 0; + pPg->needSync = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + pPg = pPg->pDirty; + } + pPager->pDirty = 0; +#ifndef NDEBUG + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( !pPg->alwaysRollback ); + assert( !pHist->pOrig ); + assert( !pHist->pStmt ); + } +#endif + pPager->pStmt = 0; + pPager->state = PAGER_SHARED; + pagerLeave(pPager); + return SQLITE_OK; + } + assert( pPager->journalOpen || !pPager->dirtyCache ); + assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); + rc = pager_end_transaction(pPager); + rc = pager_error(pPager, rc); + pagerLeave(pPager); + return rc; +} + +/* +** Rollback all changes. The database falls back to PAGER_SHARED mode. +** All in-memory cache pages revert to their original data contents. +** The journal is deleted. +** +** This routine cannot fail unless some other process is not following +** the correct locking protocol or unless some other +** process is writing trash into the journal file (SQLITE_CORRUPT) or +** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error +** codes are returned for all these occasions. Otherwise, +** SQLITE_OK is returned. +*/ +int sqlite3PagerRollback(Pager *pPager){ + int rc; + PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager)); + if( MEMDB ){ + PgHdr *p; + for(p=pPager->pAll; p; p=p->pNextAll){ + PgHistory *pHist; + assert( !p->alwaysRollback ); + if( !p->dirty ){ + assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig ); + assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt ); + continue; + } + + pHist = PGHDR_TO_HIST(p, pPager); + if( pHist->pOrig ){ + memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize); + PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager)); + }else{ + PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager)); + } + clearHistory(pHist); + p->dirty = 0; + p->inJournal = 0; + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + if( pPager->xReiniter ){ + pPager->xReiniter(p, pPager->pageSize); + } + } + pPager->pDirty = 0; + pPager->pStmt = 0; + pPager->dbSize = pPager->origDbSize; + pager_truncate_cache(pPager); + pPager->stmtInUse = 0; + pPager->state = PAGER_SHARED; + return SQLITE_OK; + } + + pagerEnter(pPager); + if( !pPager->dirtyCache || !pPager->journalOpen ){ + rc = pager_end_transaction(pPager); + pagerLeave(pPager); + return rc; + } + + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + if( pPager->state>=PAGER_EXCLUSIVE ){ + pager_playback(pPager, 0); + } + pagerLeave(pPager); + return pPager->errCode; + } + if( pPager->state==PAGER_RESERVED ){ + int rc2; + rc = pager_playback(pPager, 0); + rc2 = pager_end_transaction(pPager); + if( rc==SQLITE_OK ){ + rc = rc2; + } + }else{ + rc = pager_playback(pPager, 0); + } + /* pager_reset(pPager); */ + pPager->dbSize = -1; + + /* If an error occurs during a ROLLBACK, we can no longer trust the pager + ** cache. So call pager_error() on the way out to make any error + ** persistent. + */ + rc = pager_error(pPager, rc); + pagerLeave(pPager); + return rc; +} + +/* +** Return TRUE if the database file is opened read-only. Return FALSE +** if the database is (in theory) writable. +*/ +int sqlite3PagerIsreadonly(Pager *pPager){ + return pPager->readOnly; +} + +/* +** Return the number of references to the pager. +*/ +int sqlite3PagerRefcount(Pager *pPager){ + return pPager->nRef; +} + +#ifdef SQLITE_TEST +/* +** This routine is used for testing and analysis only. +*/ +int *sqlite3PagerStats(Pager *pPager){ + static int a[11]; + a[0] = pPager->nRef; + a[1] = pPager->nPage; + a[2] = pPager->mxPage; + a[3] = pPager->dbSize; + a[4] = pPager->state; + a[5] = pPager->errCode; + a[6] = pPager->nHit; + a[7] = pPager->nMiss; + a[8] = 0; /* Used to be pPager->nOvfl */ + a[9] = pPager->nRead; + a[10] = pPager->nWrite; + return a; +} +#endif + +/* +** Set the statement rollback point. +** +** This routine should be called with the transaction journal already +** open. A new statement journal is created that can be used to rollback +** changes of a single SQL command within a larger transaction. +*/ +static int pagerStmtBegin(Pager *pPager){ + int rc; + assert( !pPager->stmtInUse ); + assert( pPager->state>=PAGER_SHARED ); + assert( pPager->dbSize>=0 ); + PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager)); + if( MEMDB ){ + pPager->stmtInUse = 1; + pPager->stmtSize = pPager->dbSize; + return SQLITE_OK; + } + if( !pPager->journalOpen ){ + pPager->stmtAutoopen = 1; + return SQLITE_OK; + } + assert( pPager->journalOpen ); + pagerLeave(pPager); + assert( pPager->aInStmt==0 ); + pPager->aInStmt = sqlite3MallocZero( pPager->dbSize/8 + 1 ); + pagerEnter(pPager); + if( pPager->aInStmt==0 ){ + /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ + return SQLITE_NOMEM; + } +#ifndef NDEBUG + rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); + if( rc ) goto stmt_begin_failed; + assert( pPager->stmtJSize == pPager->journalOff ); +#endif + pPager->stmtJSize = pPager->journalOff; + pPager->stmtSize = pPager->dbSize; + pPager->stmtHdrOff = 0; + pPager->stmtCksum = pPager->cksumInit; + if( !pPager->stmtOpen ){ + rc = sqlite3PagerOpentemp(pPager->pVfs, pPager->stfd, pPager->zStmtJrnl, + SQLITE_OPEN_SUBJOURNAL); + if( rc ){ + goto stmt_begin_failed; + } + pPager->stmtOpen = 1; + pPager->stmtNRec = 0; + } + pPager->stmtInUse = 1; + return SQLITE_OK; + +stmt_begin_failed: + if( pPager->aInStmt ){ + sqlite3_free(pPager->aInStmt); + pPager->aInStmt = 0; + } + return rc; +} +int sqlite3PagerStmtBegin(Pager *pPager){ + int rc; + pagerEnter(pPager); + rc = pagerStmtBegin(pPager); + pagerLeave(pPager); + return rc; +} + +/* +** Commit a statement. +*/ +int sqlite3PagerStmtCommit(Pager *pPager){ + pagerEnter(pPager); + if( pPager->stmtInUse ){ + PgHdr *pPg, *pNext; + PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); + if( !MEMDB ){ + /* sqlite3OsTruncate(pPager->stfd, 0); */ + sqlite3_free( pPager->aInStmt ); + pPager->aInStmt = 0; + }else{ + for(pPg=pPager->pStmt; pPg; pPg=pNext){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + pNext = pHist->pNextStmt; + assert( pHist->inStmt ); + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + sqlite3_free(pHist->pStmt); + pHist->pStmt = 0; + } + } + pPager->stmtNRec = 0; + pPager->stmtInUse = 0; + pPager->pStmt = 0; + } + pPager->stmtAutoopen = 0; + pagerLeave(pPager); + return SQLITE_OK; +} + +/* +** Rollback a statement. +*/ +int sqlite3PagerStmtRollback(Pager *pPager){ + int rc; + pagerEnter(pPager); + if( pPager->stmtInUse ){ + PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); + if( MEMDB ){ + PgHdr *pPg; + PgHistory *pHist; + for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){ + pHist = PGHDR_TO_HIST(pPg, pPager); + if( pHist->pStmt ){ + memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize); + sqlite3_free(pHist->pStmt); + pHist->pStmt = 0; + } + } + pPager->dbSize = pPager->stmtSize; + pager_truncate_cache(pPager); + rc = SQLITE_OK; + }else{ + rc = pager_stmt_playback(pPager); + } + sqlite3PagerStmtCommit(pPager); + }else{ + rc = SQLITE_OK; + } + pPager->stmtAutoopen = 0; + pagerLeave(pPager); + return rc; +} + +/* +** Return the full pathname of the database file. +*/ +const char *sqlite3PagerFilename(Pager *pPager){ + return pPager->zFilename; +} + +/* +** Return the VFS structure for the pager. +*/ +const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ + return pPager->pVfs; +} + +/* +** Return the file handle for the database file associated +** with the pager. This might return NULL if the file has +** not yet been opened. +*/ +sqlite3_file *sqlite3PagerFile(Pager *pPager){ + return pPager->fd; +} + +/* +** Return the directory of the database file. +*/ +const char *sqlite3PagerDirname(Pager *pPager){ + return pPager->zDirectory; +} + +/* +** Return the full pathname of the journal file. +*/ +const char *sqlite3PagerJournalname(Pager *pPager){ + return pPager->zJournal; +} + +/* +** Return true if fsync() calls are disabled for this pager. Return FALSE +** if fsync()s are executed normally. +*/ +int sqlite3PagerNosync(Pager *pPager){ + return pPager->noSync; +} + +#ifdef SQLITE_HAS_CODEC +/* +** Set the codec for this pager +*/ +void sqlite3PagerSetCodec( + Pager *pPager, + void *(*xCodec)(void*,void*,Pgno,int), + void *pCodecArg +){ + pPager->xCodec = xCodec; + pPager->pCodecArg = pCodecArg; +} +#endif + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Move the page pPg to location pgno in the file. +** +** There must be no references to the page previously located at +** pgno (which we call pPgOld) though that page is allowed to be +** in cache. If the page previous located at pgno is not already +** in the rollback journal, it is not put there by by this routine. +** +** References to the page pPg remain valid. Updating any +** meta-data associated with pPg (i.e. data stored in the nExtra bytes +** allocated along with the page) is the responsibility of the caller. +** +** A transaction must be active when this routine is called. It used to be +** required that a statement transaction was not active, but this restriction +** has been removed (CREATE INDEX needs to move a page when a statement +** transaction is active). +*/ +int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){ + PgHdr *pPgOld; /* The page being overwritten. */ + int h; + Pgno needSyncPgno = 0; + + pagerEnter(pPager); + assert( pPg->nRef>0 ); + + PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", + PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); + IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) + + pager_get_content(pPg); + if( pPg->needSync ){ + needSyncPgno = pPg->pgno; + assert( pPg->inJournal || (int)pgno>pPager->origDbSize ); + assert( pPg->dirty ); + assert( pPager->needSync ); + } + + /* Unlink pPg from its hash-chain */ + unlinkHashChain(pPager, pPg); + + /* If the cache contains a page with page-number pgno, remove it + ** from its hash chain. Also, if the PgHdr.needSync was set for + ** page pgno before the 'move' operation, it needs to be retained + ** for the page moved there. + */ + pPg->needSync = 0; + pPgOld = pager_lookup(pPager, pgno); + if( pPgOld ){ + assert( pPgOld->nRef==0 ); + unlinkHashChain(pPager, pPgOld); + makeClean(pPgOld); + pPg->needSync = pPgOld->needSync; + }else{ + pPg->needSync = 0; + } + if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ + pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; + }else{ + pPg->inJournal = 0; + assert( pPg->needSync==0 || (int)pgno>pPager->origDbSize ); + } + + /* Change the page number for pPg and insert it into the new hash-chain. */ + assert( pgno!=0 ); + pPg->pgno = pgno; + h = pgno & (pPager->nHash-1); + if( pPager->aHash[h] ){ + assert( pPager->aHash[h]->pPrevHash==0 ); + pPager->aHash[h]->pPrevHash = pPg; + } + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + pPg->pPrevHash = 0; + + makeDirty(pPg); + pPager->dirtyCache = 1; + + if( needSyncPgno ){ + /* If needSyncPgno is non-zero, then the journal file needs to be + ** sync()ed before any data is written to database file page needSyncPgno. + ** Currently, no such page exists in the page-cache and the + ** Pager.aInJournal bit has been set. This needs to be remedied by loading + ** the page into the pager-cache and setting the PgHdr.needSync flag. + ** + ** If the attempt to load the page into the page-cache fails, (due + ** to a malloc() or IO failure), clear the bit in the aInJournal[] + ** array. Otherwise, if the page is loaded and written again in + ** this transaction, it may be written to the database file before + ** it is synced into the journal file. This way, it may end up in + ** the journal file twice, but that is not a problem. + ** + ** The sqlite3PagerGet() call may cause the journal to sync. So make + ** sure the Pager.needSync flag is set too. + */ + int rc; + PgHdr *pPgHdr; + assert( pPager->needSync ); + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); + if( rc!=SQLITE_OK ){ + if( pPager->aInJournal && (int)needSyncPgno<=pPager->origDbSize ){ + pPager->aInJournal[needSyncPgno/8] &= ~(1<<(needSyncPgno&7)); + } + pagerLeave(pPager); + return rc; + } + pPager->needSync = 1; + pPgHdr->needSync = 1; + pPgHdr->inJournal = 1; + makeDirty(pPgHdr); + sqlite3PagerUnref(pPgHdr); + } + + pagerLeave(pPager); + return SQLITE_OK; +} +#endif + +/* +** Return a pointer to the data for the specified page. +*/ +void *sqlite3PagerGetData(DbPage *pPg){ + return PGHDR_TO_DATA(pPg); +} + +/* +** Return a pointer to the Pager.nExtra bytes of "extra" space +** allocated along with the specified page. +*/ +void *sqlite3PagerGetExtra(DbPage *pPg){ + Pager *pPager = pPg->pPager; + return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0); +} + +/* +** Get/set the locking-mode for this pager. Parameter eMode must be one +** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then +** the locking-mode is set to the value specified. +** +** The returned value is either PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) +** locking-mode. +*/ +int sqlite3PagerLockingMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_LOCKINGMODE_QUERY + || eMode==PAGER_LOCKINGMODE_NORMAL + || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_QUERY<0 ); + assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); + if( eMode>=0 && !pPager->tempFile ){ + pPager->exclusiveMode = eMode; + } + return (int)pPager->exclusiveMode; +} + +#ifdef SQLITE_TEST +/* +** Print a listing of all referenced pages and their ref count. +*/ +void sqlite3PagerRefdump(Pager *pPager){ + PgHdr *pPg; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + if( pPg->nRef<=0 ) continue; + sqlite3DebugPrintf("PAGE %3d addr=%p nRef=%d\n", + pPg->pgno, PGHDR_TO_DATA(pPg), pPg->nRef); + } +} +#endif + +#endif /* SQLITE_OMIT_DISKIO */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/pager.h b/client/src/thirdparty/sqlite-3.4.2/src/pager.h new file mode 100644 index 0000000..c864a15 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/pager.h @@ -0,0 +1,125 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** subsystem. The page cache subsystem reads and writes a file a page +** at a time and provides a journal for rollback. +** +** @(#) $Id: pager.h,v 1.69 2008/02/02 20:47:38 drh Exp $ +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef unsigned int Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: This values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** See source code comments for a detailed description of the following +** routines: +*/ +int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int); +void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler); +void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int)); +void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int)); +int sqlite3PagerSetPagesize(Pager*, u16*); +int sqlite3PagerMaxPageCount(Pager*, int); +int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); +void sqlite3PagerSetCachesize(Pager*, int); +int sqlite3PagerClose(Pager *pPager); +int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +int sqlite3PagerRef(DbPage*); +int sqlite3PagerUnref(DbPage*); +int sqlite3PagerWrite(DbPage*); +int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*); +int sqlite3PagerPagecount(Pager*); +int sqlite3PagerTruncate(Pager*,Pgno); +int sqlite3PagerBegin(DbPage*, int exFlag); +int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno); +int sqlite3PagerCommitPhaseTwo(Pager*); +int sqlite3PagerRollback(Pager*); +int sqlite3PagerIsreadonly(Pager*); +int sqlite3PagerStmtBegin(Pager*); +int sqlite3PagerStmtCommit(Pager*); +int sqlite3PagerStmtRollback(Pager*); +void sqlite3PagerDontRollback(DbPage*); +void sqlite3PagerDontWrite(DbPage*); +int sqlite3PagerRefcount(Pager*); +void sqlite3PagerSetSafetyLevel(Pager*,int,int); +const char *sqlite3PagerFilename(Pager*); +const sqlite3_vfs *sqlite3PagerVfs(Pager*); +sqlite3_file *sqlite3PagerFile(Pager*); +const char *sqlite3PagerDirname(Pager*); +const char *sqlite3PagerJournalname(Pager*); +int sqlite3PagerNosync(Pager*); +int sqlite3PagerMovepage(Pager*,DbPage*,Pgno); +void *sqlite3PagerGetData(DbPage *); +void *sqlite3PagerGetExtra(DbPage *); +int sqlite3PagerLockingMode(Pager *, int); +void *sqlite3PagerTempSpace(Pager*); + +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) + int sqlite3PagerReleaseMemory(int); +#endif + +#ifdef SQLITE_HAS_CODEC + void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); +#endif + +#if !defined(NDEBUG) || defined(SQLITE_TEST) + Pgno sqlite3PagerPagenumber(DbPage*); + int sqlite3PagerIswriteable(DbPage*); +#endif + +#ifdef SQLITE_TEST + int *sqlite3PagerStats(Pager*); + void sqlite3PagerRefdump(Pager*); +#endif + +#ifdef SQLITE_TEST +void disable_simulated_io_errors(void); +void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/parse.y b/client/src/thirdparty/sqlite-3.4.2/src/parse.y new file mode 100644 index 0000000..7766341 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/parse.y @@ -0,0 +1,1114 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains SQLite's grammar for SQL. Process this file +** using the lemon parser generator to generate C code that runs +** the parser. Lemon will also generate a header file containing +** numeric codes for all of the tokens. +** +** @(#) $Id: parse.y,v 1.240 2008/01/22 23:37:10 drh Exp $ +*/ + +// All token codes are small integers with #defines that begin with "TK_" +%token_prefix TK_ + +// The type of the data attached to each token is Token. This is also the +// default type for non-terminals. +// +%token_type {Token} +%default_type {Token} + +// The generated parser function takes a 4th argument as follows: +%extra_argument {Parse *pParse} + +// This code runs whenever there is a syntax error +// +%syntax_error { + assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); + pParse->parseError = 1; +} +%stack_overflow { + sqlite3ErrorMsg(pParse, "parser stack overflow"); + pParse->parseError = 1; +} + +// The name of the generated procedure that implements the parser +// is as follows: +%name sqlite3Parser + +// The following text is included near the beginning of the C source +// code file that implements the parser. +// +%include { +#include "sqliteInt.h" + +/* +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. +*/ +struct LimitVal { + Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ + Expr *pOffset; /* The OFFSET expression. NULL if there is none */ +}; + +/* +** An instance of this structure is used to store the LIKE, +** GLOB, NOT LIKE, and NOT GLOB operators. +*/ +struct LikeOp { + Token eOperator; /* "like" or "glob" or "regexp" */ + int not; /* True if the NOT keyword is present */ +}; + +/* +** An instance of the following structure describes the event of a +** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, +** TK_DELETE, or TK_INSTEAD. If the event is of the form +** +** UPDATE ON (a,b,c) +** +** Then the "b" IdList records the list "a,b,c". +*/ +struct TrigEvent { int a; IdList * b; }; + +/* +** An instance of this structure holds the ATTACH key and the key type. +*/ +struct AttachKey { int type; Token key; }; + +} // end %include + +// Input is a single SQL command +input ::= cmdlist. +cmdlist ::= cmdlist ecmd. +cmdlist ::= ecmd. +cmdx ::= cmd. { sqlite3FinishCoding(pParse); } +ecmd ::= SEMI. +ecmd ::= explain cmdx SEMI. +explain ::= . { sqlite3BeginParse(pParse, 0); } +%ifndef SQLITE_OMIT_EXPLAIN +explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); } +explain ::= EXPLAIN QUERY PLAN. { sqlite3BeginParse(pParse, 2); } +%endif SQLITE_OMIT_EXPLAIN + +///////////////////// Begin and end transactions. //////////////////////////// +// + +cmd ::= BEGIN transtype(Y) trans_opt. {sqlite3BeginTransaction(pParse, Y);} +trans_opt ::= . +trans_opt ::= TRANSACTION. +trans_opt ::= TRANSACTION nm. +%type transtype {int} +transtype(A) ::= . {A = TK_DEFERRED;} +transtype(A) ::= DEFERRED(X). {A = @X;} +transtype(A) ::= IMMEDIATE(X). {A = @X;} +transtype(A) ::= EXCLUSIVE(X). {A = @X;} +cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);} +cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);} +cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);} + +///////////////////// The CREATE TABLE statement //////////////////////////// +// +cmd ::= create_table create_table_args. +create_table ::= CREATE temp(T) TABLE ifnotexists(E) nm(Y) dbnm(Z). { + sqlite3StartTable(pParse,&Y,&Z,T,0,0,E); +} +%type ifnotexists {int} +ifnotexists(A) ::= . {A = 0;} +ifnotexists(A) ::= IF NOT EXISTS. {A = 1;} +%type temp {int} +%ifndef SQLITE_OMIT_TEMPDB +temp(A) ::= TEMP. {A = 1;} +%endif SQLITE_OMIT_TEMPDB +temp(A) ::= . {A = 0;} +create_table_args ::= LP columnlist conslist_opt(X) RP(Y). { + sqlite3EndTable(pParse,&X,&Y,0); +} +create_table_args ::= AS select(S). { + sqlite3EndTable(pParse,0,0,S); + sqlite3SelectDelete(S); +} +columnlist ::= columnlist COMMA column. +columnlist ::= column. + +// A "column" is a complete description of a single column in a +// CREATE TABLE statement. This includes the column name, its +// datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES, +// NOT NULL and so forth. +// +column(A) ::= columnid(X) type carglist. { + A.z = X.z; + A.n = (pParse->sLastToken.z-X.z) + pParse->sLastToken.n; +} +columnid(A) ::= nm(X). { + sqlite3AddColumn(pParse,&X); + A = X; +} + + +// An IDENTIFIER can be a generic identifier, or one of several +// keywords. Any non-standard keyword can also be an identifier. +// +%type id {Token} +id(A) ::= ID(X). {A = X;} + +// The following directive causes tokens ABORT, AFTER, ASC, etc. to +// fallback to ID if they will not parse as their original value. +// This obviates the need for the "id" nonterminal. +// +%fallback ID + ABORT AFTER ANALYZE ASC ATTACH BEFORE BEGIN CASCADE CAST CONFLICT + DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR + IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH PLAN + QUERY KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW + TEMP TRIGGER VACUUM VIEW VIRTUAL +%ifdef SQLITE_OMIT_COMPOUND_SELECT + EXCEPT INTERSECT UNION +%endif SQLITE_OMIT_COMPOUND_SELECT + REINDEX RENAME CTIME_KW IF + . +%wildcard ANY. + +// Define operator precedence early so that this is the first occurance +// of the operator tokens in the grammer. Keeping the operators together +// causes them to be assigned integer values that are close together, +// which keeps parser tables smaller. +// +// The token values assigned to these symbols is determined by the order +// in which lemon first sees them. It must be the case that ISNULL/NOTNULL, +// NE/EQ, GT/LE, and GE/LT are separated by only a single value. See +// the sqlite3ExprIfFalse() routine for additional information on this +// constraint. +// +%left OR. +%left AND. +%right NOT. +%left IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ. +%left GT LE LT GE. +%right ESCAPE. +%left BITAND BITOR LSHIFT RSHIFT. +%left PLUS MINUS. +%left STAR SLASH REM. +%left CONCAT. +%left COLLATE. +%right UMINUS UPLUS BITNOT. + +// And "ids" is an identifer-or-string. +// +%type ids {Token} +ids(A) ::= ID|STRING(X). {A = X;} + +// The name of a column or table can be any of the following: +// +%type nm {Token} +nm(A) ::= ID(X). {A = X;} +nm(A) ::= STRING(X). {A = X;} +nm(A) ::= JOIN_KW(X). {A = X;} + +// A typetoken is really one or more tokens that form a type name such +// as can be found after the column name in a CREATE TABLE statement. +// Multiple tokens are concatenated to form the value of the typetoken. +// +%type typetoken {Token} +type ::= . +type ::= typetoken(X). {sqlite3AddColumnType(pParse,&X);} +typetoken(A) ::= typename(X). {A = X;} +typetoken(A) ::= typename(X) LP signed RP(Y). { + A.z = X.z; + A.n = &Y.z[Y.n] - X.z; +} +typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). { + A.z = X.z; + A.n = &Y.z[Y.n] - X.z; +} +%type typename {Token} +typename(A) ::= ids(X). {A = X;} +typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(Y.z-X.z);} +signed ::= plus_num. +signed ::= minus_num. + +// "carglist" is a list of additional constraints that come after the +// column name and column type in a CREATE TABLE statement. +// +carglist ::= carglist carg. +carglist ::= . +carg ::= CONSTRAINT nm ccons. +carg ::= ccons. +ccons ::= DEFAULT term(X). {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT LP expr(X) RP. {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT PLUS term(X). {sqlite3AddDefaultValue(pParse,X);} +ccons ::= DEFAULT MINUS term(X). { + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0); + sqlite3AddDefaultValue(pParse,p); +} +ccons ::= DEFAULT id(X). { + Expr *p = sqlite3PExpr(pParse, TK_STRING, 0, 0, &X); + sqlite3AddDefaultValue(pParse,p); +} + +// In addition to the type name, we also care about the primary key and +// UNIQUE constraints. +// +ccons ::= NULL onconf. +ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);} +ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). + {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} +ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} +ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);} +ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). + {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} +ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} +ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);} + +// The optional AUTOINCREMENT keyword +%type autoinc {int} +autoinc(X) ::= . {X = 0;} +autoinc(X) ::= AUTOINCR. {X = 1;} + +// The next group of rules parses the arguments to a REFERENCES clause +// that determine if the referential integrity checking is deferred or +// or immediate and which determine what action to take if a ref-integ +// check fails. +// +%type refargs {int} +refargs(A) ::= . { A = OE_Restrict * 0x010101; } +refargs(A) ::= refargs(X) refarg(Y). { A = (X & Y.mask) | Y.value; } +%type refarg {struct {int value; int mask;}} +refarg(A) ::= MATCH nm. { A.value = 0; A.mask = 0x000000; } +refarg(A) ::= ON DELETE refact(X). { A.value = X; A.mask = 0x0000ff; } +refarg(A) ::= ON UPDATE refact(X). { A.value = X<<8; A.mask = 0x00ff00; } +refarg(A) ::= ON INSERT refact(X). { A.value = X<<16; A.mask = 0xff0000; } +%type refact {int} +refact(A) ::= SET NULL. { A = OE_SetNull; } +refact(A) ::= SET DEFAULT. { A = OE_SetDflt; } +refact(A) ::= CASCADE. { A = OE_Cascade; } +refact(A) ::= RESTRICT. { A = OE_Restrict; } +%type defer_subclause {int} +defer_subclause(A) ::= NOT DEFERRABLE init_deferred_pred_opt(X). {A = X;} +defer_subclause(A) ::= DEFERRABLE init_deferred_pred_opt(X). {A = X;} +%type init_deferred_pred_opt {int} +init_deferred_pred_opt(A) ::= . {A = 0;} +init_deferred_pred_opt(A) ::= INITIALLY DEFERRED. {A = 1;} +init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE. {A = 0;} + +// For the time being, the only constraint we care about is the primary +// key and UNIQUE. Both create indices. +// +conslist_opt(A) ::= . {A.n = 0; A.z = 0;} +conslist_opt(A) ::= COMMA(X) conslist. {A = X;} +conslist ::= conslist COMMA tcons. +conslist ::= conslist tcons. +conslist ::= tcons. +tcons ::= CONSTRAINT nm. +tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). + {sqlite3AddPrimaryKey(pParse,X,R,I,0);} +tcons ::= UNIQUE LP idxlist(X) RP onconf(R). + {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);} +tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);} +tcons ::= FOREIGN KEY LP idxlist(FA) RP + REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { + sqlite3CreateForeignKey(pParse, FA, &T, TA, R); + sqlite3DeferForeignKey(pParse, D); +} +%type defer_subclause_opt {int} +defer_subclause_opt(A) ::= . {A = 0;} +defer_subclause_opt(A) ::= defer_subclause(X). {A = X;} + +// The following is a non-standard extension that allows us to declare the +// default behavior when there is a constraint conflict. +// +%type onconf {int} +%type orconf {int} +%type resolvetype {int} +onconf(A) ::= . {A = OE_Default;} +onconf(A) ::= ON CONFLICT resolvetype(X). {A = X;} +orconf(A) ::= . {A = OE_Default;} +orconf(A) ::= OR resolvetype(X). {A = X;} +resolvetype(A) ::= raisetype(X). {A = X;} +resolvetype(A) ::= IGNORE. {A = OE_Ignore;} +resolvetype(A) ::= REPLACE. {A = OE_Replace;} + +////////////////////////// The DROP TABLE ///////////////////////////////////// +// +cmd ::= DROP TABLE ifexists(E) fullname(X). { + sqlite3DropTable(pParse, X, 0, E); +} +%type ifexists {int} +ifexists(A) ::= IF EXISTS. {A = 1;} +ifexists(A) ::= . {A = 0;} + +///////////////////// The CREATE VIEW statement ///////////////////////////// +// +%ifndef SQLITE_OMIT_VIEW +cmd ::= CREATE(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) AS select(S). { + sqlite3CreateView(pParse, &X, &Y, &Z, S, T, E); +} +cmd ::= DROP VIEW ifexists(E) fullname(X). { + sqlite3DropTable(pParse, X, 1, E); +} +%endif SQLITE_OMIT_VIEW + +//////////////////////// The SELECT statement ///////////////////////////////// +// +cmd ::= select(X). { + SelectDest dest = {SRT_Callback, 0, 0}; + sqlite3Select(pParse, X, &dest, 0, 0, 0, 0); + sqlite3SelectDelete(X); +} + +%type select {Select*} +%destructor select {sqlite3SelectDelete($$);} +%type oneselect {Select*} +%destructor oneselect {sqlite3SelectDelete($$);} + +select(A) ::= oneselect(X). {A = X;} +%ifndef SQLITE_OMIT_COMPOUND_SELECT +select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { + if( Z ){ + Z->op = Y; + Z->pPrior = X; + }else{ + sqlite3SelectDelete(X); + } + A = Z; +} +%type multiselect_op {int} +multiselect_op(A) ::= UNION(OP). {A = @OP;} +multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} +multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;} +%endif SQLITE_OMIT_COMPOUND_SELECT +oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) + groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { + A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset); +} + +// The "distinct" nonterminal is true (1) if the DISTINCT keyword is +// present and false (0) if it is not. +// +%type distinct {int} +distinct(A) ::= DISTINCT. {A = 1;} +distinct(A) ::= ALL. {A = 0;} +distinct(A) ::= . {A = 0;} + +// selcollist is a list of expressions that are to become the return +// values of the SELECT statement. The "*" in statements like +// "SELECT * FROM ..." is encoded as a special expression with an +// opcode of TK_ALL. +// +%type selcollist {ExprList*} +%destructor selcollist {sqlite3ExprListDelete($$);} +%type sclp {ExprList*} +%destructor sclp {sqlite3ExprListDelete($$);} +sclp(A) ::= selcollist(X) COMMA. {A = X;} +sclp(A) ::= . {A = 0;} +selcollist(A) ::= sclp(P) expr(X) as(Y). { + A = sqlite3ExprListAppend(pParse,P,X,Y.n?&Y:0); +} +selcollist(A) ::= sclp(P) STAR. { + Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0); + A = sqlite3ExprListAppend(pParse, P, p, 0); +} +selcollist(A) ::= sclp(P) nm(X) DOT STAR. { + Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0); + Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); + Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); + A = sqlite3ExprListAppend(pParse,P, pDot, 0); +} + +// An option "AS " phrase that can follow one of the expressions that +// define the result set, or one of the tables in the FROM clause. +// +%type as {Token} +as(X) ::= AS nm(Y). {X = Y;} +as(X) ::= ids(Y). {X = Y;} +as(X) ::= . {X.n = 0;} + + +%type seltablist {SrcList*} +%destructor seltablist {sqlite3SrcListDelete($$);} +%type stl_prefix {SrcList*} +%destructor stl_prefix {sqlite3SrcListDelete($$);} +%type from {SrcList*} +%destructor from {sqlite3SrcListDelete($$);} + +// A complete FROM clause. +// +from(A) ::= . {A = sqlite3DbMallocZero(pParse->db, sizeof(*A));} +from(A) ::= FROM seltablist(X). { + A = X; + sqlite3SrcListShiftJoinType(A); +} + +// "seltablist" is a "Select Table List" - the content of the FROM clause +// in a SELECT statement. "stl_prefix" is a prefix of this list. +// +stl_prefix(A) ::= seltablist(X) joinop(Y). { + A = X; + if( A && A->nSrc>0 ) A->a[A->nSrc-1].jointype = Y; +} +stl_prefix(A) ::= . {A = 0;} +seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) on_opt(N) using_opt(U). { + A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U); +} +%ifndef SQLITE_OMIT_SUBQUERY + seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP + as(Z) on_opt(N) using_opt(U). { + A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U); + } + + // A seltablist_paren nonterminal represents anything in a FROM that + // is contained inside parentheses. This can be either a subquery or + // a grouping of table and subqueries. + // + %type seltablist_paren {Select*} + %destructor seltablist_paren {sqlite3SelectDelete($$);} + seltablist_paren(A) ::= select(S). {A = S;} + seltablist_paren(A) ::= seltablist(F). { + sqlite3SrcListShiftJoinType(F); + A = sqlite3SelectNew(pParse,0,F,0,0,0,0,0,0,0); + } +%endif SQLITE_OMIT_SUBQUERY + +%type dbnm {Token} +dbnm(A) ::= . {A.z=0; A.n=0;} +dbnm(A) ::= DOT nm(X). {A = X;} + +%type fullname {SrcList*} +%destructor fullname {sqlite3SrcListDelete($$);} +fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);} + +%type joinop {int} +%type joinop2 {int} +joinop(X) ::= COMMA|JOIN. { X = JT_INNER; } +joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); } +joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); } +joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN. + { X = sqlite3JoinType(pParse,&A,&B,&C); } + +%type on_opt {Expr*} +%destructor on_opt {sqlite3ExprDelete($$);} +on_opt(N) ::= ON expr(E). {N = E;} +on_opt(N) ::= . {N = 0;} + +%type using_opt {IdList*} +%destructor using_opt {sqlite3IdListDelete($$);} +using_opt(U) ::= USING LP inscollist(L) RP. {U = L;} +using_opt(U) ::= . {U = 0;} + + +%type orderby_opt {ExprList*} +%destructor orderby_opt {sqlite3ExprListDelete($$);} +%type sortlist {ExprList*} +%destructor sortlist {sqlite3ExprListDelete($$);} +%type sortitem {Expr*} +%destructor sortitem {sqlite3ExprDelete($$);} + +orderby_opt(A) ::= . {A = 0;} +orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} +sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). { + A = sqlite3ExprListAppend(pParse,X,Y,0); + if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +sortlist(A) ::= sortitem(Y) sortorder(Z). { + A = sqlite3ExprListAppend(pParse,0,Y,0); + if( A && A->a ) A->a[0].sortOrder = Z; +} +sortitem(A) ::= expr(X). {A = X;} + +%type sortorder {int} + +sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;} +sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} +sortorder(A) ::= . {A = SQLITE_SO_ASC;} + +%type groupby_opt {ExprList*} +%destructor groupby_opt {sqlite3ExprListDelete($$);} +groupby_opt(A) ::= . {A = 0;} +groupby_opt(A) ::= GROUP BY nexprlist(X). {A = X;} + +%type having_opt {Expr*} +%destructor having_opt {sqlite3ExprDelete($$);} +having_opt(A) ::= . {A = 0;} +having_opt(A) ::= HAVING expr(X). {A = X;} + +%type limit_opt {struct LimitVal} + +// The destructor for limit_opt will never fire in the current grammar. +// The limit_opt non-terminal only occurs at the end of a single production +// rule for SELECT statements. As soon as the rule that create the +// limit_opt non-terminal reduces, the SELECT statement rule will also +// reduce. So there is never a limit_opt non-terminal on the stack +// except as a transient. So there is never anything to destroy. +// +//%destructor limit_opt { +// sqlite3ExprDelete($$.pLimit); +// sqlite3ExprDelete($$.pOffset); +//} +limit_opt(A) ::= . {A.pLimit = 0; A.pOffset = 0;} +limit_opt(A) ::= LIMIT expr(X). {A.pLimit = X; A.pOffset = 0;} +limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). + {A.pLimit = X; A.pOffset = Y;} +limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). + {A.pOffset = X; A.pLimit = Y;} + +/////////////////////////// The DELETE statement ///////////////////////////// +// +cmd ::= DELETE FROM fullname(X) where_opt(Y). {sqlite3DeleteFrom(pParse,X,Y);} + +%type where_opt {Expr*} +%destructor where_opt {sqlite3ExprDelete($$);} + +where_opt(A) ::= . {A = 0;} +where_opt(A) ::= WHERE expr(X). {A = X;} + +////////////////////////// The UPDATE command //////////////////////////////// +// +cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z). { + sqlite3ExprListCheckLength(pParse,Y,SQLITE_MAX_COLUMN,"set list"); + sqlite3Update(pParse,X,Y,Z,R); +} + +%type setlist {ExprList*} +%destructor setlist {sqlite3ExprListDelete($$);} + +setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). + {A = sqlite3ExprListAppend(pParse,Z,Y,&X);} +setlist(A) ::= nm(X) EQ expr(Y). + {A = sqlite3ExprListAppend(pParse,0,Y,&X);} + +////////////////////////// The INSERT command ///////////////////////////////// +// +cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) + VALUES LP itemlist(Y) RP. + {sqlite3Insert(pParse, X, Y, 0, F, R);} +cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S). + {sqlite3Insert(pParse, X, 0, S, F, R);} +cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES. + {sqlite3Insert(pParse, X, 0, 0, F, R);} + +%type insert_cmd {int} +insert_cmd(A) ::= INSERT orconf(R). {A = R;} +insert_cmd(A) ::= REPLACE. {A = OE_Replace;} + + +%type itemlist {ExprList*} +%destructor itemlist {sqlite3ExprListDelete($$);} + +itemlist(A) ::= itemlist(X) COMMA expr(Y). + {A = sqlite3ExprListAppend(pParse,X,Y,0);} +itemlist(A) ::= expr(X). + {A = sqlite3ExprListAppend(pParse,0,X,0);} + +%type inscollist_opt {IdList*} +%destructor inscollist_opt {sqlite3IdListDelete($$);} +%type inscollist {IdList*} +%destructor inscollist {sqlite3IdListDelete($$);} + +inscollist_opt(A) ::= . {A = 0;} +inscollist_opt(A) ::= LP inscollist(X) RP. {A = X;} +inscollist(A) ::= inscollist(X) COMMA nm(Y). + {A = sqlite3IdListAppend(pParse->db,X,&Y);} +inscollist(A) ::= nm(Y). + {A = sqlite3IdListAppend(pParse->db,0,&Y);} + +/////////////////////////// Expression Processing ///////////////////////////// +// + +%type expr {Expr*} +%destructor expr {sqlite3ExprDelete($$);} +%type term {Expr*} +%destructor term {sqlite3ExprDelete($$);} + +expr(A) ::= term(X). {A = X;} +expr(A) ::= LP(B) expr(X) RP(E). {A = X; sqlite3ExprSpan(A,&B,&E); } +term(A) ::= NULL(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} +expr(A) ::= ID(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);} +expr(A) ::= JOIN_KW(X). {A = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);} +expr(A) ::= nm(X) DOT nm(Y). { + Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); + Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); + A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); +} +expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { + Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X); + Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y); + Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z); + Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); + A = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); +} +term(A) ::= INTEGER|FLOAT|BLOB(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} +term(A) ::= STRING(X). {A = sqlite3PExpr(pParse, @X, 0, 0, &X);} +expr(A) ::= REGISTER(X). {A = sqlite3RegisterExpr(pParse, &X);} +expr(A) ::= VARIABLE(X). { + Token *pToken = &X; + Expr *pExpr = A = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); + sqlite3ExprAssignVarNumber(pParse, pExpr); +} +expr(A) ::= expr(E) COLLATE ids(C). { + A = sqlite3ExprSetColl(pParse, E, &C); +} +%ifndef SQLITE_OMIT_CAST +expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { + A = sqlite3PExpr(pParse, TK_CAST, E, 0, &T); + sqlite3ExprSpan(A,&X,&Y); +} +%endif SQLITE_OMIT_CAST +expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). { + if( Y && Y->nExpr>SQLITE_MAX_FUNCTION_ARG ){ + sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X); + } + A = sqlite3ExprFunction(pParse, Y, &X); + sqlite3ExprSpan(A,&X,&E); + if( D && A ){ + A->flags |= EP_Distinct; + } +} +expr(A) ::= ID(X) LP STAR RP(E). { + A = sqlite3ExprFunction(pParse, 0, &X); + sqlite3ExprSpan(A,&X,&E); +} +term(A) ::= CTIME_KW(OP). { + /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are + ** treated as functions that return constants */ + A = sqlite3ExprFunction(pParse, 0,&OP); + if( A ){ + A->op = TK_CONST_FUNC; + A->span = OP; + } +} +expr(A) ::= expr(X) AND(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) OR(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). + {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y). + {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).{A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y). + {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +expr(A) ::= expr(X) CONCAT(OP) expr(Y). {A = sqlite3PExpr(pParse,@OP,X,Y,0);} +%type likeop {struct LikeOp} +likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.not = 0;} +likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.not = 1;} +likeop(A) ::= MATCH(X). {A.eOperator = X; A.not = 0;} +likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.not = 1;} +%type escape {Expr*} +%destructor escape {sqlite3ExprDelete($$);} +escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;} +escape(X) ::= . [ESCAPE] {X = 0;} +expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] { + ExprList *pList; + pList = sqlite3ExprListAppend(pParse,0, Y, 0); + pList = sqlite3ExprListAppend(pParse,pList, X, 0); + if( E ){ + pList = sqlite3ExprListAppend(pParse,pList, E, 0); + } + A = sqlite3ExprFunction(pParse, pList, &OP.eOperator); + if( OP.not ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A, &X->span, &Y->span); + if( A ) A->flags |= EP_InfixFunc; +} + +expr(A) ::= expr(X) ISNULL|NOTNULL(E). { + A = sqlite3PExpr(pParse, @E, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) IS NULL(E). { + A = sqlite3PExpr(pParse, TK_ISNULL, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) NOT NULL(E). { + A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= expr(X) IS NOT NULL(E). { + A = sqlite3PExpr(pParse, TK_NOTNULL, X, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); +} +expr(A) ::= NOT(B) expr(X). { + A = sqlite3PExpr(pParse, @B, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= BITNOT(B) expr(X). { + A = sqlite3PExpr(pParse, @B, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= MINUS(B) expr(X). [UMINUS] { + A = sqlite3PExpr(pParse, TK_UMINUS, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +expr(A) ::= PLUS(B) expr(X). [UPLUS] { + A = sqlite3PExpr(pParse, TK_UPLUS, X, 0, 0); + sqlite3ExprSpan(A,&B,&X->span); +} +%type between_op {int} +between_op(A) ::= BETWEEN. {A = 0;} +between_op(A) ::= NOT BETWEEN. {A = 1;} +expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] { + ExprList *pList = sqlite3ExprListAppend(pParse,0, X, 0); + pList = sqlite3ExprListAppend(pParse,pList, Y, 0); + A = sqlite3PExpr(pParse, TK_BETWEEN, W, 0, 0); + if( A ){ + A->pList = pList; + }else{ + sqlite3ExprListDelete(pList); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&W->span,&Y->span); +} +%ifndef SQLITE_OMIT_SUBQUERY + %type in_op {int} + in_op(A) ::= IN. {A = 0;} + in_op(A) ::= NOT IN. {A = 1;} + expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] { + A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); + if( A ){ + A->pList = Y; + sqlite3ExprSetHeight(A); + }else{ + sqlite3ExprListDelete(Y); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); + } + expr(A) ::= LP(B) select(X) RP(E). { + A = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( A ){ + A->pSelect = X; + sqlite3ExprSetHeight(A); + }else{ + sqlite3SelectDelete(X); + } + sqlite3ExprSpan(A,&B,&E); + } + expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] { + A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); + if( A ){ + A->pSelect = Y; + sqlite3ExprSetHeight(A); + }else{ + sqlite3SelectDelete(Y); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&X->span,&E); + } + expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] { + SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); + A = sqlite3PExpr(pParse, TK_IN, X, 0, 0); + if( A ){ + A->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + sqlite3ExprSetHeight(A); + }else{ + sqlite3SrcListDelete(pSrc); + } + if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0, 0); + sqlite3ExprSpan(A,&X->span,Z.z?&Z:&Y); + } + expr(A) ::= EXISTS(B) LP select(Y) RP(E). { + Expr *p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + if( p ){ + p->pSelect = Y; + sqlite3ExprSpan(p,&B,&E); + sqlite3ExprSetHeight(A); + }else{ + sqlite3SelectDelete(Y); + } + } +%endif SQLITE_OMIT_SUBQUERY + +/* CASE expressions */ +expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). { + A = sqlite3PExpr(pParse, TK_CASE, X, Z, 0); + if( A ){ + A->pList = Y; + sqlite3ExprSetHeight(A); + }else{ + sqlite3ExprListDelete(Y); + } + sqlite3ExprSpan(A, &C, &E); +} +%type case_exprlist {ExprList*} +%destructor case_exprlist {sqlite3ExprListDelete($$);} +case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). { + A = sqlite3ExprListAppend(pParse,X, Y, 0); + A = sqlite3ExprListAppend(pParse,A, Z, 0); +} +case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). { + A = sqlite3ExprListAppend(pParse,0, Y, 0); + A = sqlite3ExprListAppend(pParse,A, Z, 0); +} +%type case_else {Expr*} +%destructor case_else {sqlite3ExprDelete($$);} +case_else(A) ::= ELSE expr(X). {A = X;} +case_else(A) ::= . {A = 0;} +%type case_operand {Expr*} +%destructor case_operand {sqlite3ExprDelete($$);} +case_operand(A) ::= expr(X). {A = X;} +case_operand(A) ::= . {A = 0;} + +%type exprlist {ExprList*} +%destructor exprlist {sqlite3ExprListDelete($$);} +%type nexprlist {ExprList*} +%destructor nexprlist {sqlite3ExprListDelete($$);} + +exprlist(A) ::= nexprlist(X). {A = X;} +exprlist(A) ::= . {A = 0;} +nexprlist(A) ::= nexprlist(X) COMMA expr(Y). + {A = sqlite3ExprListAppend(pParse,X,Y,0);} +nexprlist(A) ::= expr(Y). + {A = sqlite3ExprListAppend(pParse,0,Y,0);} + + +///////////////////////////// The CREATE INDEX command /////////////////////// +// +cmd ::= CREATE(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) + ON nm(Y) LP idxlist(Z) RP(E). { + sqlite3CreateIndex(pParse, &X, &D, + sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U, + &S, &E, SQLITE_SO_ASC, NE); +} + +%type uniqueflag {int} +uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} +uniqueflag(A) ::= . {A = OE_None;} + +%type idxlist {ExprList*} +%destructor idxlist {sqlite3ExprListDelete($$);} +%type idxlist_opt {ExprList*} +%destructor idxlist_opt {sqlite3ExprListDelete($$);} +%type idxitem {Token} + +idxlist_opt(A) ::= . {A = 0;} +idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} +idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder(Z). { + Expr *p = 0; + if( C.n>0 ){ + p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + sqlite3ExprSetColl(pParse, p, &C); + } + A = sqlite3ExprListAppend(pParse,X, p, &Y); + sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index"); + if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). { + Expr *p = 0; + if( C.n>0 ){ + p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); + sqlite3ExprSetColl(pParse, p, &C); + } + A = sqlite3ExprListAppend(pParse,0, p, &Y); + sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index"); + if( A ) A->a[A->nExpr-1].sortOrder = Z; +} +idxitem(A) ::= nm(X). {A = X;} + +%type collate {Token} +collate(C) ::= . {C.z = 0; C.n = 0;} +collate(C) ::= COLLATE ids(X). {C = X;} + + +///////////////////////////// The DROP INDEX command ///////////////////////// +// +cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);} + +///////////////////////////// The VACUUM command ///////////////////////////// +// +%ifndef SQLITE_OMIT_VACUUM +%ifndef SQLITE_OMIT_ATTACH +cmd ::= VACUUM. {sqlite3Vacuum(pParse);} +cmd ::= VACUUM nm. {sqlite3Vacuum(pParse);} +%endif SQLITE_OMIT_ATTACH +%endif SQLITE_OMIT_VACUUM + +///////////////////////////// The PRAGMA command ///////////////////////////// +// +%ifndef SQLITE_OMIT_PRAGMA +cmd ::= PRAGMA nm(X) dbnm(Z) EQ nmnum(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ ON(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). { + sqlite3Pragma(pParse,&X,&Z,&Y,1); +} +cmd ::= PRAGMA nm(X) dbnm(Z) LP nmnum(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);} +cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);} +nmnum(A) ::= plus_num(X). {A = X;} +nmnum(A) ::= nm(X). {A = X;} +%endif SQLITE_OMIT_PRAGMA +plus_num(A) ::= plus_opt number(X). {A = X;} +minus_num(A) ::= MINUS number(X). {A = X;} +number(A) ::= INTEGER|FLOAT(X). {A = X;} +plus_opt ::= PLUS. +plus_opt ::= . + +//////////////////////////// The CREATE TRIGGER command ///////////////////// + +%ifndef SQLITE_OMIT_TRIGGER + +cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). { + Token all; + all.z = A.z; + all.n = (Z.z - A.z) + Z.n; + sqlite3FinishTrigger(pParse, S, &all); +} + +trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z) + trigger_time(C) trigger_event(D) + ON fullname(E) foreach_clause when_clause(G). { + sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR); + A = (Z.n==0?B:Z); +} + +%type trigger_time {int} +trigger_time(A) ::= BEFORE. { A = TK_BEFORE; } +trigger_time(A) ::= AFTER. { A = TK_AFTER; } +trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;} +trigger_time(A) ::= . { A = TK_BEFORE; } + +%type trigger_event {struct TrigEvent} +%destructor trigger_event {sqlite3IdListDelete($$.b);} +trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;} +trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;} +trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X;} + +foreach_clause ::= . +foreach_clause ::= FOR EACH ROW. + +%type when_clause {Expr*} +%destructor when_clause {sqlite3ExprDelete($$);} +when_clause(A) ::= . { A = 0; } +when_clause(A) ::= WHEN expr(X). { A = X; } + +%type trigger_cmd_list {TriggerStep*} +%destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);} +trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. { + if( Y ){ + Y->pLast->pNext = X; + }else{ + Y = X; + } + Y->pLast = X; + A = Y; +} +trigger_cmd_list(A) ::= . { A = 0; } + +%type trigger_cmd {TriggerStep*} +%destructor trigger_cmd {sqlite3DeleteTriggerStep($$);} +// UPDATE +trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z). + { A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); } + +// INSERT +trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) + VALUES LP itemlist(Y) RP. + {A = sqlite3TriggerInsertStep(pParse->db, &X, F, Y, 0, R);} + +trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) select(S). + {A = sqlite3TriggerInsertStep(pParse->db, &X, F, 0, S, R);} + +// DELETE +trigger_cmd(A) ::= DELETE FROM nm(X) where_opt(Y). + {A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);} + +// SELECT +trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); } + +// The special RAISE expression that may occur in trigger programs +expr(A) ::= RAISE(X) LP IGNORE RP(Y). { + A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( A ){ + A->iColumn = OE_Ignore; + sqlite3ExprSpan(A, &X, &Y); + } +} +expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { + A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z); + if( A ) { + A->iColumn = T; + sqlite3ExprSpan(A, &X, &Y); + } +} +%endif !SQLITE_OMIT_TRIGGER + +%type raisetype {int} +raisetype(A) ::= ROLLBACK. {A = OE_Rollback;} +raisetype(A) ::= ABORT. {A = OE_Abort;} +raisetype(A) ::= FAIL. {A = OE_Fail;} + + +//////////////////////// DROP TRIGGER statement ////////////////////////////// +%ifndef SQLITE_OMIT_TRIGGER +cmd ::= DROP TRIGGER ifexists(NOERR) fullname(X). { + sqlite3DropTrigger(pParse,X,NOERR); +} +%endif !SQLITE_OMIT_TRIGGER + +//////////////////////// ATTACH DATABASE file AS name ///////////////////////// +%ifndef SQLITE_OMIT_ATTACH +cmd ::= ATTACH database_kw_opt expr(F) AS expr(D) key_opt(K). { + sqlite3Attach(pParse, F, D, K); +} +cmd ::= DETACH database_kw_opt expr(D). { + sqlite3Detach(pParse, D); +} + +%type key_opt {Expr*} +%destructor key_opt {sqlite3ExprDelete($$);} +key_opt(A) ::= . { A = 0; } +key_opt(A) ::= KEY expr(X). { A = X; } + +database_kw_opt ::= DATABASE. +database_kw_opt ::= . +%endif SQLITE_OMIT_ATTACH + +////////////////////////// REINDEX collation ////////////////////////////////// +%ifndef SQLITE_OMIT_REINDEX +cmd ::= REINDEX. {sqlite3Reindex(pParse, 0, 0);} +cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);} +%endif SQLITE_OMIT_REINDEX + +/////////////////////////////////// ANALYZE /////////////////////////////////// +%ifndef SQLITE_OMIT_ANALYZE +cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0);} +cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);} +%endif + +//////////////////////// ALTER TABLE table ... //////////////////////////////// +%ifndef SQLITE_OMIT_ALTERTABLE +cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). { + sqlite3AlterRenameTable(pParse,X,&Z); +} +cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column(Y). { + sqlite3AlterFinishAddColumn(pParse, &Y); +} +add_column_fullname ::= fullname(X). { + sqlite3AlterBeginAddColumn(pParse, X); +} +kwcolumn_opt ::= . +kwcolumn_opt ::= COLUMNKW. +%endif SQLITE_OMIT_ALTERTABLE + +//////////////////////// CREATE VIRTUAL TABLE ... ///////////////////////////// +%ifndef SQLITE_OMIT_VIRTUALTABLE +cmd ::= create_vtab. {sqlite3VtabFinishParse(pParse,0);} +cmd ::= create_vtab LP vtabarglist RP(X). {sqlite3VtabFinishParse(pParse,&X);} +create_vtab ::= CREATE VIRTUAL TABLE nm(X) dbnm(Y) USING nm(Z). { + sqlite3VtabBeginParse(pParse, &X, &Y, &Z); +} +vtabarglist ::= vtabarg. +vtabarglist ::= vtabarglist COMMA vtabarg. +vtabarg ::= . {sqlite3VtabArgInit(pParse);} +vtabarg ::= vtabarg vtabargtoken. +vtabargtoken ::= ANY(X). {sqlite3VtabArgExtend(pParse,&X);} +vtabargtoken ::= lp anylist RP(X). {sqlite3VtabArgExtend(pParse,&X);} +lp ::= LP(X). {sqlite3VtabArgExtend(pParse,&X);} +anylist ::= . +anylist ::= anylist ANY(X). {sqlite3VtabArgExtend(pParse,&X);} +%endif SQLITE_OMIT_VIRTUALTABLE diff --git a/client/src/thirdparty/sqlite-3.4.2/src/pragma.c b/client/src/thirdparty/sqlite-3.4.2/src/pragma.c new file mode 100644 index 0000000..dc7db61 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/pragma.c @@ -0,0 +1,1227 @@ +/* +** 2003 April 6 +** +** 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 used to implement the PRAGMA command. +** +** $Id: pragma.c,v 1.169 2008/01/22 01:48:09 drh Exp $ +*/ +#include "sqliteInt.h" +#include + +/* Ignore this whole file if pragmas are disabled +*/ +#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) + +/* +** Interpret the given string as a safety level. Return 0 for OFF, +** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or +** unrecognized string argument. +** +** Note that the values returned are one less that the values that +** should be passed into sqlite3BtreeSetSafetyLevel(). The is done +** to support legacy SQL code. The safety level used to be boolean +** and older scripts may have used numbers 0 for OFF and 1 for ON. +*/ +static int getSafetyLevel(const char *z){ + /* 123456789 123456789 */ + static const char zText[] = "onoffalseyestruefull"; + static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; + static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; + static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; + int i, n; + if( isdigit(*z) ){ + return atoi(z); + } + n = strlen(z); + for(i=0; i=0&&i<=2)?i:0); +} +#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Interpret the given string as a temp db location. Return 1 for file +** backed temporary databases, 2 for the Red-Black tree in memory database +** and 0 to use the compile-time default. +*/ +static int getTempStore(const char *z){ + if( z[0]>='0' && z[0]<='2' ){ + return z[0] - '0'; + }else if( sqlite3StrICmp(z, "file")==0 ){ + return 1; + }else if( sqlite3StrICmp(z, "memory")==0 ){ + return 2; + }else{ + return 0; + } +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Invalidate temp storage, either when the temp storage is changed +** from default, or when 'file' and the temp_store_directory has changed +*/ +static int invalidateTempStorage(Parse *pParse){ + sqlite3 *db = pParse->db; + if( db->aDb[1].pBt!=0 ){ + if( !db->autoCommit ){ + sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " + "from within a transaction"); + return SQLITE_ERROR; + } + sqlite3BtreeClose(db->aDb[1].pBt); + db->aDb[1].pBt = 0; + sqlite3ResetInternalSchema(db, 0); + } + return SQLITE_OK; +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** If the TEMP database is open, close it and mark the database schema +** as needing reloading. This must be done when using the TEMP_STORE +** or DEFAULT_TEMP_STORE pragmas. +*/ +static int changeTempStorage(Parse *pParse, const char *zStorageType){ + int ts = getTempStore(zStorageType); + sqlite3 *db = pParse->db; + if( db->temp_store==ts ) return SQLITE_OK; + if( invalidateTempStorage( pParse ) != SQLITE_OK ){ + return SQLITE_ERROR; + } + db->temp_store = ts; + return SQLITE_OK; +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +/* +** Generate code to return a single integer value. +*/ +static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ + Vdbe *v = sqlite3GetVdbe(pParse); + int mem = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Integer, value, mem); + if( pParse->explain==0 ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P4_STATIC); + } + sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); +} + +#ifndef SQLITE_OMIT_FLAG_PRAGMAS +/* +** Check to see if zRight and zLeft refer to a pragma that queries +** or changes one of the flags in db->flags. Return 1 if so and 0 if not. +** Also, implement the pragma. +*/ +static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ + static const struct sPragmaType { + const char *zName; /* Name of the pragma */ + int mask; /* Mask for the db->flags value */ + } aPragma[] = { + { "full_column_names", SQLITE_FullColNames }, + { "short_column_names", SQLITE_ShortColNames }, + { "count_changes", SQLITE_CountRows }, + { "empty_result_callbacks", SQLITE_NullCallback }, + { "legacy_file_format", SQLITE_LegacyFileFmt }, + { "fullfsync", SQLITE_FullFSync }, +#ifdef SQLITE_DEBUG + { "sql_trace", SQLITE_SqlTrace }, + { "vdbe_listing", SQLITE_VdbeListing }, + { "vdbe_trace", SQLITE_VdbeTrace }, +#endif +#ifndef SQLITE_OMIT_CHECK + { "ignore_check_constraints", SQLITE_IgnoreChecks }, +#endif + /* The following is VERY experimental */ + { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, + { "omit_readlock", SQLITE_NoReadlock }, + + /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted + ** flag if there are any active statements. */ + { "read_uncommitted", SQLITE_ReadUncommitted }, + }; + int i; + const struct sPragmaType *p; + for(i=0, p=aPragma; izName)==0 ){ + sqlite3 *db = pParse->db; + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + if( zRight==0 ){ + returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); + }else{ + if( getBoolean(zRight) ){ + db->flags |= p->mask; + }else{ + db->flags &= ~p->mask; + } + + /* Many of the flag-pragmas modify the code generated by the SQL + ** compiler (eg. count_changes). So add an opcode to expire all + ** compiled SQL statements after modifying a pragma value. + */ + sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); + } + } + + return 1; + } + } + return 0; +} +#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ + +/* +** Process a pragma statement. +** +** Pragmas are of this form: +** +** PRAGMA [database.]id [= value] +** +** The identifier might also be a string. The value is a string, and +** identifier, or a number. If minusFlag is true, then the value is +** a number that was preceded by a minus sign. +** +** If the left side is "database.id" then pId1 is the database name +** and pId2 is the id. If the left side is just "id" then pId1 is the +** id and pId2 is any empty string. +*/ +void sqlite3Pragma( + Parse *pParse, + Token *pId1, /* First part of [database.]id field */ + Token *pId2, /* Second part of [database.]id field, or NULL */ + Token *pValue, /* Token for , or NULL */ + int minusFlag /* True if a '-' sign preceded */ +){ + char *zLeft = 0; /* Nul-terminated UTF-8 string */ + char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ + const char *zDb = 0; /* The database name */ + Token *pId; /* Pointer to token */ + int iDb; /* Database index for */ + sqlite3 *db = pParse->db; + Db *pDb; + Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); + if( v==0 ) return; + pParse->nMem = 2; + + /* Interpret the [database.] part of the pragma statement. iDb is the + ** index of the database this pragma is being applied to in db.aDb[]. */ + iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); + if( iDb<0 ) return; + pDb = &db->aDb[iDb]; + + /* If the temp database has been explicitly named as part of the + ** pragma, make sure it is open. + */ + if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ + return; + } + + zLeft = sqlite3NameFromToken(db, pId); + if( !zLeft ) return; + if( minusFlag ){ + zRight = sqlite3MPrintf(db, "-%T", pValue); + }else{ + zRight = sqlite3NameFromToken(db, pValue); + } + + zDb = ((iDb>0)?pDb->zName:0); + if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ + goto pragma_out; + } + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + /* + ** PRAGMA [database.]default_cache_size + ** PRAGMA [database.]default_cache_size=N + ** + ** The first form reports the current persistent setting for the + ** page cache size. The value returned is the maximum number of + ** pages in the page cache. The second form sets both the current + ** page cache size value and the persistent page cache size value + ** stored in the database file. + ** + ** The default cache size is stored in meta-value 2 of page 1 of the + ** database file. The cache size is actually the absolute value of + ** this memory location. The sign of meta-value 2 determines the + ** synchronous setting. A negative value means synchronous is off + ** and a positive value means synchronous is on. + */ + if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ + static const VdbeOpList getCacheSize[] = { + { OP_ReadCookie, 0, 1, 2}, /* 0 */ + { OP_IfPos, 1, 6, 0}, + { OP_Integer, 0, 2, 0}, + { OP_Subtract, 1, 2, 1}, + { OP_IfPos, 1, 6, 0}, + { OP_Integer, 0, 1, 0}, /* 5 */ + { OP_ResultRow, 1, 1, 0}, + }; + int addr; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeUsesBtree(v, iDb); + if( !zRight ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC); + pParse->nMem += 2; + addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); + }else{ + int size = atoi(zRight); + if( size<0 ) size = -size; + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, size, 1); + sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, 2); + addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0); + sqlite3VdbeAddOp2(v, OP_Integer, -size, 1); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 2, 1); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + } + }else + + /* + ** PRAGMA [database.]page_size + ** PRAGMA [database.]page_size=N + ** + ** The first form reports the current setting for the + ** database page size in bytes. The second form sets the + ** database page size value. The value can only be set if + ** the database has not yet been created. + */ + if( sqlite3StrICmp(zLeft,"page_size")==0 ){ + Btree *pBt = pDb->pBt; + if( !zRight ){ + int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0; + returnSingleInt(pParse, "page_size", size); + }else{ + /* Malloc may fail when setting the page-size, as there is an internal + ** buffer that the pager module resizes using sqlite3_realloc(). + */ + if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1) ){ + db->mallocFailed = 1; + } + } + }else + + /* + ** PRAGMA [database.]max_page_count + ** PRAGMA [database.]max_page_count=N + ** + ** The first form reports the current setting for the + ** maximum number of pages in the database file. The + ** second form attempts to change this setting. Both + ** forms return the current setting. + */ + if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){ + Btree *pBt = pDb->pBt; + int newMax = 0; + if( zRight ){ + newMax = atoi(zRight); + } + if( pBt ){ + newMax = sqlite3BtreeMaxPageCount(pBt, newMax); + } + returnSingleInt(pParse, "max_page_count", newMax); + }else + + /* + ** PRAGMA [database.]locking_mode + ** PRAGMA [database.]locking_mode = (normal|exclusive) + */ + if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){ + const char *zRet = "normal"; + int eMode = getLockingMode(zRight); + + if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){ + /* Simple "PRAGMA locking_mode;" statement. This is a query for + ** the current default locking mode (which may be different to + ** the locking-mode of the main database). + */ + eMode = db->dfltLockMode; + }else{ + Pager *pPager; + if( pId2->n==0 ){ + /* This indicates that no database name was specified as part + ** of the PRAGMA command. In this case the locking-mode must be + ** set on all attached databases, as well as the main db file. + ** + ** Also, the sqlite3.dfltLockMode variable is set so that + ** any subsequently attached databases also use the specified + ** locking mode. + */ + int ii; + assert(pDb==&db->aDb[0]); + for(ii=2; iinDb; ii++){ + pPager = sqlite3BtreePager(db->aDb[ii].pBt); + sqlite3PagerLockingMode(pPager, eMode); + } + db->dfltLockMode = eMode; + } + pPager = sqlite3BtreePager(pDb->pBt); + eMode = sqlite3PagerLockingMode(pPager, eMode); + } + + assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE); + if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ + zRet = "exclusive"; + } + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P4_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + + /* + ** PRAGMA [database.]auto_vacuum + ** PRAGMA [database.]auto_vacuum=N + ** + ** Get or set the (boolean) value of the database 'auto-vacuum' parameter. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){ + Btree *pBt = pDb->pBt; + if( sqlite3ReadSchema(pParse) ){ + goto pragma_out; + } + if( !zRight ){ + int auto_vacuum = + pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM; + returnSingleInt(pParse, "auto_vacuum", auto_vacuum); + }else{ + int eAuto = getAutoVacuum(zRight); + db->nextAutovac = eAuto; + if( eAuto>=0 ){ + /* Call SetAutoVacuum() to set initialize the internal auto and + ** incr-vacuum flags. This is required in case this connection + ** creates the database file. It is important that it is created + ** as an auto-vacuum capable db. + */ + int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); + if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ + /* When setting the auto_vacuum mode to either "full" or + ** "incremental", write the value of meta[6] in the database + ** file. Before writing to meta[6], check that meta[3] indicates + ** that this really is an auto-vacuum capable database. + */ + static const VdbeOpList setMeta6[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_ReadCookie, 0, 1, 3}, /* 1 */ + { OP_If, 1, 0, 0}, /* 2 */ + { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ + { OP_Integer, 0, 1, 0}, /* 4 */ + { OP_SetCookie, 0, 6, 1}, /* 5 */ + }; + int iAddr; + iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); + sqlite3VdbeChangeP1(v, iAddr, iDb); + sqlite3VdbeChangeP1(v, iAddr+1, iDb); + sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); + sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); + sqlite3VdbeChangeP1(v, iAddr+5, iDb); + sqlite3VdbeUsesBtree(v, iDb); + } + } + } + }else +#endif + + /* + ** PRAGMA [database.]incremental_vacuum(N) + ** + ** Do N steps of incremental vacuuming on a database. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){ + int iLimit, addr; + if( sqlite3ReadSchema(pParse) ){ + goto pragma_out; + } + if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ + iLimit = 0x7fffffff; + } + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3VdbeAddOp2(v, OP_Integer, iLimit, 1); + addr = sqlite3VdbeAddOp1(v, OP_IncrVacuum, iDb); + sqlite3VdbeAddOp1(v, OP_ResultRow, 1); + sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); + sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr); + sqlite3VdbeJumpHere(v, addr); + }else +#endif + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + /* + ** PRAGMA [database.]cache_size + ** PRAGMA [database.]cache_size=N + ** + ** The first form reports the current local setting for the + ** page cache size. The local setting can be different from + ** the persistent cache size value that is stored in the database + ** file itself. The value returned is the maximum number of + ** pages in the page cache. The second form sets the local + ** page cache size value. It does not change the persistent + ** cache size stored on the disk so the cache size will revert + ** to its default value when the database is closed and reopened. + ** N should be a positive integer. + */ + if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); + }else{ + int size = atoi(zRight); + if( size<0 ) size = -size; + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + } + }else + + /* + ** PRAGMA temp_store + ** PRAGMA temp_store = "default"|"memory"|"file" + ** + ** Return or set the local value of the temp_store flag. Changing + ** the local value does not make changes to the disk file and the default + ** value will be restored the next time the database is opened. + ** + ** Note that it is possible for the library compile-time options to + ** override this setting + */ + if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ + if( !zRight ){ + returnSingleInt(pParse, "temp_store", db->temp_store); + }else{ + changeTempStorage(pParse, zRight); + } + }else + + /* + ** PRAGMA temp_store_directory + ** PRAGMA temp_store_directory = ""|"directory_name" + ** + ** Return or set the local value of the temp_store_directory flag. Changing + ** the value sets a specific directory to be used for temporary files. + ** Setting to a null string reverts to the default temporary directory search. + ** If temporary directory is changed, then invalidateTempStorage. + ** + */ + if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){ + if( !zRight ){ + if( sqlite3_temp_directory ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "temp_store_directory", P4_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } + }else{ + if( zRight[0] + && !sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE) + ){ + sqlite3ErrorMsg(pParse, "not a writable directory"); + goto pragma_out; + } + if( TEMP_STORE==0 + || (TEMP_STORE==1 && db->temp_store<=1) + || (TEMP_STORE==2 && db->temp_store==1) + ){ + invalidateTempStorage(pParse); + } + sqlite3_free(sqlite3_temp_directory); + if( zRight[0] ){ + sqlite3_temp_directory = zRight; + zRight = 0; + }else{ + sqlite3_temp_directory = 0; + } + } + }else + + /* + ** PRAGMA [database.]synchronous + ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL + ** + ** Return or set the local value of the synchronous flag. Changing + ** the local value does not make changes to the disk file and the + ** default value will be restored the next time the database is + ** opened. + */ + if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + returnSingleInt(pParse, "synchronous", pDb->safety_level-1); + }else{ + if( !db->autoCommit ){ + sqlite3ErrorMsg(pParse, + "Safety level may not be changed inside a transaction"); + }else{ + pDb->safety_level = getSafetyLevel(zRight)+1; + } + } + }else +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_FLAG_PRAGMAS + if( flagPragma(pParse, zLeft, zRight) ){ + /* The flagPragma() subroutine also generates any necessary code + ** there is nothing more to do here */ + }else +#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ + +#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS + /* + ** PRAGMA table_info(
) + ** + ** Return a single row for each column of the named table. The columns of + ** the returned data set are: + ** + ** cid: Column id (numbered from left to right, starting at 0) + ** name: Column name + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. + */ + if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + int i; + int nHidden = 0; + Column *pCol; + sqlite3VdbeSetNumCols(v, 6); + pParse->nMem = 6; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P4_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P4_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P4_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P4_STATIC); + sqlite3ViewGetColumnNames(pParse, pTab); + for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ + const Token *pDflt; + if( IsHiddenColumn(pCol) ){ + nHidden++; + continue; + } + sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + pCol->zType ? pCol->zType : "", 0); + sqlite3VdbeAddOp2(v, OP_Integer, pCol->notNull, 4); + if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){ + sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pDflt->z, pDflt->n); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, 5); + } + sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6); + } + } + }else + + if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx ){ + int i; + pTab = pIdx->pTable; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P4_STATIC); + for(i=0; inColumn; i++){ + int cnum = pIdx->aiColumn[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); + } + } + }else + + if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite3GetVdbe(pParse); + pIdx = pTab->pIndex; + if( pIdx ){ + int i = 0; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P4_STATIC); + while(pIdx){ + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + ++i; + pIdx = pIdx->pNext; + } + } + } + }else + + if( sqlite3StrICmp(zLeft, "database_list")==0 ){ + int i; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 3); + pParse->nMem = 3; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P4_STATIC); + for(i=0; inDb; i++){ + if( db->aDb[i].pBt==0 ) continue; + assert( db->aDb[i].zName!=0 ); + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3); + } + }else + + if( sqlite3StrICmp(zLeft, "collation_list")==0 ){ + int i = 0; + HashElem *p; + sqlite3VdbeSetNumCols(v, 2); + pParse->nMem = 2; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(p); + sqlite3VdbeAddOp2(v, OP_Integer, i++, 1); + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + }else +#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ + +#ifndef SQLITE_OMIT_FOREIGN_KEY + if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){ + FKey *pFK; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite3GetVdbe(pParse); + pFK = pTab->pFKey; + if( pFK ){ + int i = 0; + sqlite3VdbeSetNumCols(v, 5); + pParse->nMem = 5; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P4_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P4_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P4_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P4_STATIC); + while(pFK){ + int j; + for(j=0; jnCol; j++){ + char *zCol = pFK->aCol[j].zCol; + sqlite3VdbeAddOp2(v, OP_Integer, i, 1); + sqlite3VdbeAddOp2(v, OP_Integer, j, 2); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0); + sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, + pTab->aCol[pFK->aCol[j].iFrom].zName, 0); + sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); + } + ++i; + pFK = pFK->pNextFrom; + } + } + } + }else +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ + +#ifndef NDEBUG + if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ + if( zRight ){ + if( getBoolean(zRight) ){ + sqlite3ParserTrace(stderr, "parser: "); + }else{ + sqlite3ParserTrace(0, 0); + } + } + }else +#endif + + /* Reinstall the LIKE and GLOB functions. The variant of LIKE + ** used will be case sensitive or not depending on the RHS. + */ + if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ + if( zRight ){ + sqlite3RegisterLikeFunctions(db, getBoolean(zRight)); + } + }else + +#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX +# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 +#endif + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK + /* Pragma "quick_check" is an experimental reduced version of + ** integrity_check designed to detect most database corruption + ** without most of the overhead of a full integrity-check. + */ + if( sqlite3StrICmp(zLeft, "integrity_check")==0 + || sqlite3StrICmp(zLeft, "quick_check")==0 + ){ + int i, j, addr, mxErr; + + /* Code that appears at the end of the integrity check. If no error + ** messages have been generated, output OK. Otherwise output the + ** error message + */ + static const VdbeOpList endCode[] = { + { OP_AddImm, 1, 0, 0}, /* 0 */ + { OP_IfNeg, 1, 0, 0}, /* 1 */ + { OP_String8, 0, 3, 0}, /* 2 */ + { OP_ResultRow, 3, 1, 0}, + }; + + int isQuick = (zLeft[0]=='q'); + + /* Initialize the VDBE program */ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pParse->nMem = 6; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P4_STATIC); + + /* Set the maximum error count */ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; + if( zRight ){ + mxErr = atoi(zRight); + if( mxErr<=0 ){ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; + } + } + sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */ + + /* Do an integrity check on each database file */ + for(i=0; inDb; i++){ + HashElem *x; + Hash *pTbls; + int cnt = 0; + + if( OMIT_TEMPDB && i==1 ) continue; + + sqlite3CodeVerifySchema(pParse, i); + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */ + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + + /* Do an integrity check of the B-Tree + ** + ** Begin by filling registers 2, 3, ... with the root pages numbers + ** for all tables and indices in the database. + */ + pTbls = &db->aDb[i].pSchema->tblHash; + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt); + cnt++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt); + cnt++; + } + } + if( cnt==0 ) continue; + + /* Make sure sufficient number of registers have been allocated */ + if( pParse->nMem < cnt+3 ){ + pParse->nMem = cnt+3; + } + + /* Do the b-tree integrity checks */ + sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1); + sqlite3VdbeChangeP5(v, i); + addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); + sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, + sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), + P4_DYNAMIC); + sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 2); + sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1); + sqlite3VdbeJumpHere(v, addr); + + /* Make sure all the indices are constructed correctly. + */ + for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + int loopTop; + + if( pTab->pIndex==0 ) continue; + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */ + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); + sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */ + loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0); + sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */ + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int jmp2; + static const VdbeOpList idxErr[] = { + { OP_AddImm, 1, -1, 0}, + { OP_String8, 0, 3, 0}, /* 1 */ + { OP_Rowid, 1, 4, 0}, + { OP_String8, 0, 5, 0}, /* 3 */ + { OP_String8, 0, 6, 0}, /* 4 */ + { OP_Concat, 4, 3, 3}, + { OP_Concat, 5, 3, 3}, + { OP_Concat, 6, 3, 3}, + { OP_ResultRow, 3, 1, 0}, + }; + sqlite3GenerateIndexKey(pParse, pIdx, 1, 3); + jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3); + addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); + sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC); + sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC); + sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_STATIC); + sqlite3VdbeJumpHere(v, jmp2); + } + sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1); + sqlite3VdbeJumpHere(v, loopTop); + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + static const VdbeOpList cntIdx[] = { + { OP_Integer, 0, 3, 0}, + { OP_Rewind, 0, 0, 0}, /* 1 */ + { OP_AddImm, 3, 1, 0}, + { OP_Next, 0, 0, 0}, /* 3 */ + { OP_Eq, 2, 0, 3}, /* 4 */ + { OP_AddImm, 1, -1, 0}, + { OP_String8, 0, 2, 0}, /* 6 */ + { OP_String8, 0, 3, 0}, /* 7 */ + { OP_Concat, 3, 2, 2}, + { OP_ResultRow, 2, 1, 0}, + }; + if( pIdx->tnum==0 ) continue; + addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); + sqlite3VdbeAddOp2(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); + sqlite3VdbeChangeP1(v, addr+1, j+2); + sqlite3VdbeChangeP2(v, addr+1, addr+4); + sqlite3VdbeChangeP1(v, addr+3, j+2); + sqlite3VdbeChangeP2(v, addr+3, addr+2); + sqlite3VdbeJumpHere(v, addr+4); + sqlite3VdbeChangeP4(v, addr+6, + "wrong # of entries in index ", P4_STATIC); + sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_STATIC); + } + } + } + addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); + sqlite3VdbeChangeP2(v, addr, -mxErr); + sqlite3VdbeJumpHere(v, addr+1); + sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC); + }else +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_UTF16 + /* + ** PRAGMA encoding + ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" + ** + ** In its first form, this pragma returns the encoding of the main + ** database. If the database is not initialized, it is initialized now. + ** + ** The second form of this pragma is a no-op if the main database file + ** has not already been initialized. In this case it sets the default + ** encoding that will be used for the main database file if a new file + ** is created. If an existing main database file is opened, then the + ** default text encoding for the existing database is used. + ** + ** In all cases new databases created using the ATTACH command are + ** created to use the same default text encoding as the main database. If + ** the main database has not been initialized and/or created when ATTACH + ** is executed, this is done before the ATTACH operation. + ** + ** In the second form this pragma sets the text encoding to be used in + ** new database files created using this database handle. It is only + ** useful if invoked immediately after the main database i + */ + if( sqlite3StrICmp(zLeft, "encoding")==0 ){ + static const struct EncName { + char *zName; + u8 enc; + } encnames[] = { + { "UTF-8", SQLITE_UTF8 }, + { "UTF8", SQLITE_UTF8 }, + { "UTF-16le", SQLITE_UTF16LE }, + { "UTF16le", SQLITE_UTF16LE }, + { "UTF-16be", SQLITE_UTF16BE }, + { "UTF16be", SQLITE_UTF16BE }, + { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */ + { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */ + { 0, 0 } + }; + const struct EncName *pEnc; + if( !zRight ){ /* "PRAGMA encoding" */ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P4_STATIC); + sqlite3VdbeAddOp2(v, OP_String8, 0, 1); + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( pEnc->enc==ENC(pParse->db) ){ + sqlite3VdbeChangeP4(v, -1, pEnc->zName, P4_STATIC); + break; + } + } + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + }else{ /* "PRAGMA encoding = XXX" */ + /* Only change the value of sqlite.enc if the database handle is not + ** initialized. If the main database exists, the new sqlite.enc value + ** will be overwritten when the schema is next loaded. If it does not + ** already exists, it will be created to use the new encoding value. + */ + if( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ + ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; + break; + } + } + if( !pEnc->zName ){ + sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); + } + } + } + }else +#endif /* SQLITE_OMIT_UTF16 */ + +#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + /* + ** PRAGMA [database.]schema_version + ** PRAGMA [database.]schema_version = + ** + ** PRAGMA [database.]user_version + ** PRAGMA [database.]user_version = + ** + ** The pragma's schema_version and user_version are used to set or get + ** the value of the schema-version and user-version, respectively. Both + ** the schema-version and the user-version are 32-bit signed integers + ** stored in the database header. + ** + ** The schema-cookie is usually only manipulated internally by SQLite. It + ** is incremented by SQLite whenever the database schema is modified (by + ** creating or dropping a table or index). 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. + ** Subverting this mechanism by using "PRAGMA schema_version" to modify + ** the schema-version is potentially dangerous and may lead to program + ** crashes or database corruption. Use with caution! + ** + ** The user-version is not used internally by SQLite. It may be used by + ** applications for any purpose. + */ + if( sqlite3StrICmp(zLeft, "schema_version")==0 + || sqlite3StrICmp(zLeft, "user_version")==0 + || sqlite3StrICmp(zLeft, "freelist_count")==0 + ){ + + int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ + sqlite3VdbeUsesBtree(v, iDb); + switch( zLeft[0] ){ + case 's': case 'S': + iCookie = 0; + break; + case 'f': case 'F': + iCookie = 1; + iDb = (-1*(iDb+1)); + assert(iDb<=0); + break; + default: + iCookie = 5; + break; + } + + if( zRight && iDb>=0 ){ + /* Write the specified cookie value */ + static const VdbeOpList setCookie[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_Integer, 0, 1, 0}, /* 1 */ + { OP_SetCookie, 0, 0, 1}, /* 2 */ + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); + sqlite3VdbeChangeP1(v, addr+2, iDb); + sqlite3VdbeChangeP2(v, addr+2, iCookie); + }else{ + /* Read the specified cookie value */ + static const VdbeOpList readCookie[] = { + { OP_ReadCookie, 0, 1, 0}, /* 0 */ + { OP_ResultRow, 1, 1, 0} + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP3(v, addr, iCookie); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P4_TRANSIENT); + } + }else +#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + /* + ** Report the current state of file logs for all databases + */ + if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ + static const char *const azLockName[] = { + "unlocked", "shared", "reserved", "pending", "exclusive" + }; + int i; + Vdbe *v = sqlite3GetVdbe(pParse); + sqlite3VdbeSetNumCols(v, 2); + pParse->nMem = 2; + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P4_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P4_STATIC); + for(i=0; inDb; i++){ + Btree *pBt; + Pager *pPager; + const char *zState = "unknown"; + int j; + if( db->aDb[i].zName==0 ) continue; + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC); + pBt = db->aDb[i].pBt; + if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ + zState = "closed"; + }else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0, + SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){ + zState = azLockName[j]; + } + sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2); + } + }else +#endif + +#ifdef SQLITE_SSE + /* + ** Check to see if the sqlite_statements table exists. Create it + ** if it does not. + */ + if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){ + extern int sqlite3CreateStatementsTable(Parse*); + sqlite3CreateStatementsTable(pParse); + }else +#endif + +#if SQLITE_HAS_CODEC + if( sqlite3StrICmp(zLeft, "key")==0 ){ + sqlite3_key(db, zRight, strlen(zRight)); + }else +#endif +#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD) + if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ +#if SQLITE_HAS_CODEC + if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ + extern void sqlite3_activate_see(const char*); + sqlite3_activate_see(&zRight[4]); + } +#endif +#ifdef SQLITE_ENABLE_CEROD + if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ + extern void sqlite3_activate_cerod(const char*); + sqlite3_activate_cerod(&zRight[6]); + } +#endif + } +#endif + + {} + + if( v ){ + /* Code an OP_Expire at the end of each PRAGMA program to cause + ** the VDBE implementing the pragma to expire. Most (all?) pragmas + ** are only valid for a single execution. + */ + sqlite3VdbeAddOp2(v, OP_Expire, 1, 0); + + /* + ** Reset the safety level, in case the fullfsync flag or synchronous + ** setting changed. + */ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + if( db->autoCommit ){ + sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, + (db->flags&SQLITE_FullFSync)!=0); + } +#endif + } +pragma_out: + sqlite3_free(zLeft); + sqlite3_free(zRight); +} + +#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/prepare.c b/client/src/thirdparty/sqlite-3.4.2/src/prepare.c new file mode 100644 index 0000000..a9bc844 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/prepare.c @@ -0,0 +1,768 @@ +/* +** 2005 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. +** +************************************************************************* +** This file contains the implementation of the sqlite3_prepare() +** interface, and routines that contribute to loading the database schema +** from disk. +** +** $Id: prepare.c,v 1.75 2008/01/23 03:03:05 drh Exp $ +*/ +#include "sqliteInt.h" +#include + +/* +** Fill the InitData structure with an error message that indicates +** that the database is corrupt. +*/ +static void corruptSchema(InitData *pData, const char *zExtra){ + if( !pData->db->mallocFailed ){ + sqlite3SetString(pData->pzErrMsg, "malformed database schema", + zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0); + } + pData->rc = SQLITE_CORRUPT; +} + +/* +** This is the callback routine for the code that initializes the +** database. See sqlite3Init() below for additional information. +** This routine is also called from the OP_ParseSchema opcode of the VDBE. +** +** Each callback contains the following information: +** +** argv[0] = name of thing being created +** argv[1] = root page number for table or index. 0 for trigger or view. +** argv[2] = SQL text for the CREATE statement. +** +*/ +int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ + InitData *pData = (InitData*)pInit; + sqlite3 *db = pData->db; + int iDb = pData->iDb; + + assert( sqlite3_mutex_held(db->mutex) ); + pData->rc = SQLITE_OK; + DbClearProperty(db, iDb, DB_Empty); + if( db->mallocFailed ){ + corruptSchema(pData, 0); + return SQLITE_NOMEM; + } + + assert( argc==3 ); + if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ + if( argv[1]==0 ){ + corruptSchema(pData, 0); + return 1; + } + assert( iDb>=0 && iDbnDb ); + if( argv[2] && argv[2][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 + ** structures that describe the table, index, or view. + */ + char *zErr; + int rc; + assert( db->init.busy ); + db->init.iDb = iDb; + db->init.newTnum = atoi(argv[1]); + rc = sqlite3_exec(db, argv[2], 0, 0, &zErr); + db->init.iDb = 0; + assert( rc!=SQLITE_OK || zErr==0 ); + if( SQLITE_OK!=rc ){ + pData->rc = rc; + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + }else if( rc!=SQLITE_INTERRUPT ){ + corruptSchema(pData, zErr); + } + sqlite3_free(zErr); + return 1; + } + }else if( argv[0]==0 ){ + corruptSchema(pData, 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 + ** constraint for a CREATE TABLE. The index should have already + ** been created when we processed the CREATE TABLE. All we have + ** to do here is record the root page number for that index. + */ + Index *pIndex; + pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName); + if( pIndex==0 || pIndex->tnum!=0 ){ + /* This can occur if there exists an index on a TEMP table which + ** has the same name as another index on a permanent index. Since + ** the permanent table is hidden by the TEMP table, we can also + ** safely ignore the index on the permanent table. + */ + /* Do Nothing */; + }else{ + pIndex->tnum = atoi(argv[1]); + } + } + return 0; +} + +/* +** Attempt to read the database schema and initialize internal +** data structures for a single database file. The index of the +** database file is given by iDb. iDb==0 is used for the main +** database. iDb==1 should never be used. iDb>=2 is used for +** auxiliary databases. Return one of the SQLITE_ error codes to +** indicate success or failure. +*/ +static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ + int rc; + BtCursor *curMain; + int size; + Table *pTab; + Db *pDb; + char const *azArg[4]; + int meta[10]; + InitData initData; + char const *zMasterSchema; + char const *zMasterName = SCHEMA_TABLE(iDb); + + /* + ** The master database table has a structure like this + */ + static const char master_schema[] = + "CREATE TABLE sqlite_master(\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")" + ; +#ifndef SQLITE_OMIT_TEMPDB + static const char temp_master_schema[] = + "CREATE TEMP TABLE sqlite_temp_master(\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")" + ; +#else + #define temp_master_schema 0 +#endif + + assert( iDb>=0 && iDbnDb ); + assert( db->aDb[iDb].pSchema ); + assert( sqlite3_mutex_held(db->mutex) ); + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + + /* zMasterSchema and zInitScript are set to point at the master schema + ** and initialisation script appropriate for the database being + ** initialised. zMasterName is the name of the master table. + */ + if( !OMIT_TEMPDB && iDb==1 ){ + zMasterSchema = temp_master_schema; + }else{ + zMasterSchema = master_schema; + } + zMasterName = SCHEMA_TABLE(iDb); + + /* Construct the schema tables. */ + azArg[0] = zMasterName; + azArg[1] = "1"; + azArg[2] = zMasterSchema; + azArg[3] = 0; + initData.db = db; + initData.iDb = iDb; + initData.pzErrMsg = pzErrMsg; + (void)sqlite3SafetyOff(db); + rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0); + (void)sqlite3SafetyOn(db); + if( rc ){ + rc = initData.rc; + goto error_out; + } + pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName); + if( pTab ){ + pTab->readOnly = 1; + } + + /* Create a cursor to hold the database open + */ + pDb = &db->aDb[iDb]; + if( pDb->pBt==0 ){ + if( !OMIT_TEMPDB && iDb==1 ){ + DbSetProperty(db, 1, DB_SchemaLoaded); + } + return SQLITE_OK; + } + sqlite3BtreeEnter(pDb->pBt); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain); + if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ + sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); + sqlite3BtreeLeave(pDb->pBt); + goto error_out; + } + + /* Get the database meta information. + ** + ** Meta values are as follows: + ** meta[0] Schema cookie. Changes with each schema change. + ** meta[1] File format of schema layer. + ** meta[2] Size of the page cache. + ** meta[3] Use freelist if 0. Autovacuum if greater than zero. + ** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE + ** meta[5] The user cookie. Used by the application. + ** meta[6] Incremental-vacuum flag. + ** meta[7] + ** meta[8] + ** meta[9] + ** + ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to + ** the possible values of meta[4]. + */ + if( rc==SQLITE_OK ){ + int i; + for(i=0; rc==SQLITE_OK && ipBt, i+1, (u32 *)&meta[i]); + } + if( rc ){ + sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); + sqlite3BtreeCloseCursor(curMain); + sqlite3BtreeLeave(pDb->pBt); + goto error_out; + } + }else{ + memset(meta, 0, sizeof(meta)); + } + pDb->pSchema->schema_cookie = meta[0]; + + /* If opening a non-empty database, check the text encoding. For the + ** main database, set sqlite3.enc to the encoding of the main database. + ** For an attached db, it is an error if the encoding is not the same + ** as sqlite3.enc. + */ + if( meta[4] ){ /* text encoding */ + if( iDb==0 ){ + /* If opening the main database, set ENC(db). */ + ENC(db) = (u8)meta[4]; + db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0); + }else{ + /* If opening an attached database, the encoding much match ENC(db) */ + if( meta[4]!=ENC(db) ){ + sqlite3BtreeCloseCursor(curMain); + sqlite3SetString(pzErrMsg, "attached databases must use the same" + " text encoding as main database", (char*)0); + sqlite3BtreeLeave(pDb->pBt); + return SQLITE_ERROR; + } + } + }else{ + DbSetProperty(db, iDb, DB_Empty); + } + pDb->pSchema->enc = ENC(db); + + size = meta[2]; + if( size==0 ){ size = SQLITE_DEFAULT_CACHE_SIZE; } + if( size<0 ) size = -size; + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + + /* + ** file_format==1 Version 3.0.0. + ** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN + ** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults + ** file_format==4 Version 3.3.0. // DESC indices. Boolean constants + */ + pDb->pSchema->file_format = meta[1]; + if( pDb->pSchema->file_format==0 ){ + pDb->pSchema->file_format = 1; + } + if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ + sqlite3BtreeCloseCursor(curMain); + sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); + sqlite3BtreeLeave(pDb->pBt); + return SQLITE_ERROR; + } + + /* Ticket #2804: When we open a database in the newer file format, + ** clear the legacy_file_format pragma flag so that a VACUUM will + ** not downgrade the database and thus invalidate any descending + ** indices that the user might have created. + */ + if( iDb==0 && meta[1]>=4 ){ + db->flags &= ~SQLITE_LegacyFileFmt; + } + + /* Read the schema information out of the schema tables + */ + assert( db->init.busy ); + if( rc==SQLITE_EMPTY ){ + /* For an empty database, there is nothing to read */ + rc = SQLITE_OK; + }else{ + char *zSql; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s", + db->aDb[iDb].zName, zMasterName); + (void)sqlite3SafetyOff(db); +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + xAuth = db->xAuth; + db->xAuth = 0; +#endif + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); +#ifndef SQLITE_OMIT_AUTHORIZATION + db->xAuth = xAuth; + } +#endif + if( rc==SQLITE_ABORT ) rc = initData.rc; + (void)sqlite3SafetyOn(db); + sqlite3_free(zSql); +#ifndef SQLITE_OMIT_ANALYZE + if( rc==SQLITE_OK ){ + sqlite3AnalysisLoad(db, iDb); + } +#endif + sqlite3BtreeCloseCursor(curMain); + } + if( db->mallocFailed ){ + /* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */ + rc = SQLITE_NOMEM; + sqlite3ResetInternalSchema(db, 0); + } + if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ + /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider + ** the schema loaded, even if errors occured. In this situation the + ** current sqlite3_prepare() operation will fail, but the following one + ** will attempt to compile the supplied statement against whatever subset + ** of the schema was loaded before the error occured. The primary + ** purpose of this is to allow access to the sqlite_master table + ** even when its contents have been corrupted. + */ + DbSetProperty(db, iDb, DB_SchemaLoaded); + rc = SQLITE_OK; + } + sqlite3BtreeLeave(pDb->pBt); + +error_out: + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + } + return rc; +} + +/* +** Initialize all database files - the main database file, the file +** used to store temporary tables, and any additional database files +** created using ATTACH statements. Return a success code. If an +** error occurs, write an error message into *pzErrMsg. +** +** After a database is initialized, the DB_SchemaLoaded bit is set +** bit is set in the flags field of the Db structure. If the database +** file was of zero-length, then the DB_Empty flag is also set. +*/ +int sqlite3Init(sqlite3 *db, char **pzErrMsg){ + int i, rc; + int commit_internal = !(db->flags&SQLITE_InternChanges); + + assert( sqlite3_mutex_held(db->mutex) ); + if( db->init.busy ) return SQLITE_OK; + rc = SQLITE_OK; + db->init.busy = 1; + for(i=0; rc==SQLITE_OK && inDb; i++){ + if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; + rc = sqlite3InitOne(db, i, pzErrMsg); + if( rc ){ + sqlite3ResetInternalSchema(db, i); + } + } + + /* Once all the other databases have been initialised, load the schema + ** for the TEMP database. This is loaded last, as the TEMP database + ** schema may contain references to objects in other databases. + */ +#ifndef SQLITE_OMIT_TEMPDB + if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ + rc = sqlite3InitOne(db, 1, pzErrMsg); + if( rc ){ + sqlite3ResetInternalSchema(db, 1); + } + } +#endif + + db->init.busy = 0; + if( rc==SQLITE_OK && commit_internal ){ + sqlite3CommitInternalChanges(db); + } + + return rc; +} + +/* +** This routine is a no-op if the database schema is already initialised. +** Otherwise, the schema is loaded. An error code is returned. +*/ +int sqlite3ReadSchema(Parse *pParse){ + int rc = SQLITE_OK; + sqlite3 *db = pParse->db; + assert( sqlite3_mutex_held(db->mutex) ); + if( !db->init.busy ){ + rc = sqlite3Init(db, &pParse->zErrMsg); + } + if( rc!=SQLITE_OK ){ + pParse->rc = rc; + pParse->nErr++; + } + return rc; +} + + +/* +** Check schema cookies in all databases. If any cookie is out +** of date, return 0. If all schema cookies are current, return 1. +*/ +static int schemaIsValid(sqlite3 *db){ + int iDb; + int rc; + BtCursor *curTemp; + int cookie; + int allOk = 1; + + assert( sqlite3_mutex_held(db->mutex) ); + for(iDb=0; allOk && iDbnDb; iDb++){ + Btree *pBt; + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) continue; + rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); + if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ + allOk = 0; + } + sqlite3BtreeCloseCursor(curTemp); + } + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; + } + } + return allOk; +} + +/* +** Convert a schema pointer into the iDb index that indicates +** which database file in db->aDb[] the schema refers to. +** +** If the same database is attached more than once, the first +** attached database is returned. +*/ +int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ + int i = -1000000; + + /* If pSchema is NULL, then return -1000000. This happens when code in + ** expr.c is trying to resolve a reference to a transient table (i.e. one + ** created by a sub-select). In this case the return value of this + ** function should never be used. + ** + ** We return -1000000 instead of the more usual -1 simply because using + ** -1000000 as incorrectly using -1000000 index into db->aDb[] is much + ** more likely to cause a segfault than -1 (of course there are assert() + ** statements too, but it never hurts to play the odds). + */ + assert( sqlite3_mutex_held(db->mutex) ); + if( pSchema ){ + for(i=0; inDb; i++){ + if( db->aDb[i].pSchema==pSchema ){ + break; + } + } + assert( i>=0 &&i>=0 && inDb ); + } + return i; +} + +/* +** Compile the UTF-8 encoded SQL statement zSql into a statement handle. +*/ +int sqlite3Prepare( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + Parse sParse; + char *zErrMsg = 0; + int rc = SQLITE_OK; + int i; + + assert( ppStmt ); + *ppStmt = 0; + if( sqlite3SafetyOn(db) ){ + return SQLITE_MISUSE; + } + assert( !db->mallocFailed ); + assert( sqlite3_mutex_held(db->mutex) ); + + /* If any attached database schemas are locked, do not proceed with + ** compilation. Instead return SQLITE_LOCKED immediately. + */ + for(i=0; inDb; i++) { + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + int rc; + rc = sqlite3BtreeSchemaLocked(pBt); + if( rc ){ + const char *zDb = db->aDb[i].zName; + sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb); + (void)sqlite3SafetyOff(db); + return SQLITE_LOCKED; + } + } + } + + memset(&sParse, 0, sizeof(sParse)); + sParse.db = db; + if( nBytes>=0 && zSql[nBytes]!=0 ){ + char *zSqlCopy; + if( SQLITE_MAX_SQL_LENGTH>0 && nBytes>SQLITE_MAX_SQL_LENGTH ){ + sqlite3Error(db, SQLITE_TOOBIG, "statement too long"); + (void)sqlite3SafetyOff(db); + return SQLITE_TOOBIG; + } + zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); + if( zSqlCopy ){ + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqlite3_free(zSqlCopy); + } + sParse.zTail = &zSql[nBytes]; + }else{ + sqlite3RunParser(&sParse, zSql, &zErrMsg); + } + + if( db->mallocFailed ){ + sParse.rc = SQLITE_NOMEM; + } + if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; + if( sParse.checkSchema && !schemaIsValid(db) ){ + sParse.rc = SQLITE_SCHEMA; + } + if( sParse.rc==SQLITE_SCHEMA ){ + sqlite3ResetInternalSchema(db, 0); + } + if( db->mallocFailed ){ + sParse.rc = SQLITE_NOMEM; + } + if( pzTail ){ + *pzTail = sParse.zTail; + } + rc = sParse.rc; + +#ifndef SQLITE_OMIT_EXPLAIN + if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){ + if( sParse.explain==2 ){ + sqlite3VdbeSetNumCols(sParse.pVdbe, 3); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P4_STATIC); + }else{ + sqlite3VdbeSetNumCols(sParse.pVdbe, 8); + sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 5, COLNAME_NAME, "p4", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 6, COLNAME_NAME, "p5", P4_STATIC); + sqlite3VdbeSetColName(sParse.pVdbe, 7, COLNAME_NAME, "comment",P4_STATIC); + } + } +#endif + + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + + if( saveSqlFlag ){ + sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql); + } + if( rc!=SQLITE_OK || db->mallocFailed ){ + sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); + assert(!(*ppStmt)); + }else{ + *ppStmt = (sqlite3_stmt*)sParse.pVdbe; + } + + if( zErrMsg ){ + sqlite3Error(db, rc, "%s", zErrMsg); + sqlite3_free(zErrMsg); + }else{ + sqlite3Error(db, rc, 0); + } + + rc = sqlite3ApiExit(db, rc); + assert( (rc&db->errMask)==rc ); + return rc; +} +static int sqlite3LockAndPrepare( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + int rc; + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); + rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail); + sqlite3BtreeLeaveAll(db); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Rerun the compilation of a statement after a schema change. +** Return true if the statement was recompiled successfully. +** Return false if there is an error of some kind. +*/ +int sqlite3Reprepare(Vdbe *p){ + int rc; + sqlite3_stmt *pNew; + const char *zSql; + sqlite3 *db; + + assert( sqlite3_mutex_held(sqlite3VdbeDb(p)->mutex) ); + zSql = sqlite3_sql((sqlite3_stmt *)p); + assert( zSql!=0 ); /* Reprepare only called for prepare_v2() statements */ + db = sqlite3VdbeDb(p); + assert( sqlite3_mutex_held(db->mutex) ); + rc = sqlite3LockAndPrepare(db, zSql, -1, 0, &pNew, 0); + if( rc ){ + if( rc==SQLITE_NOMEM ){ + db->mallocFailed = 1; + } + assert( pNew==0 ); + return 0; + }else{ + assert( pNew!=0 ); + } + sqlite3VdbeSwap((Vdbe*)pNew, p); + sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); + sqlite3VdbeResetStepResult((Vdbe*)pNew); + sqlite3VdbeFinalize((Vdbe*)pNew); + return 1; +} + + +/* +** Two versions of the official API. Legacy and new use. In the legacy +** version, the original SQL text is not saved in the prepared statement +** and so if a schema change occurs, SQLITE_SCHEMA is returned by +** sqlite3_step(). In the new version, the original SQL text is retained +** and the statement is automatically recompiled if an schema change +** occurs. +*/ +int sqlite3_prepare( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + return sqlite3LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail); +} +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle. */ + const char *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const char **pzTail /* OUT: End of parsed string */ +){ + return sqlite3LockAndPrepare(db,zSql,nBytes,1,ppStmt,pzTail); +} + + +#ifndef SQLITE_OMIT_UTF16 +/* +** Compile the UTF-16 encoded SQL statement zSql into a statement handle. +*/ +static int sqlite3Prepare16( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + /* This function currently works by first transforming the UTF-16 + ** encoded string to UTF-8, then invoking sqlite3_prepare(). The + ** tricky bit is figuring out the pointer to return in *pzTail. + */ + char *zSql8; + const char *zTail8 = 0; + int rc = SQLITE_OK; + + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE; + } + sqlite3_mutex_enter(db->mutex); + zSql8 = sqlite3Utf16to8(db, zSql, nBytes); + if( zSql8 ){ + rc = sqlite3LockAndPrepare(db, zSql8, -1, saveSqlFlag, ppStmt, &zTail8); + } + + if( zTail8 && pzTail ){ + /* If sqlite3_prepare returns a tail pointer, we calculate the + ** equivalent pointer into the UTF-16 string by counting the unicode + ** characters between zSql8 and zTail8, and then returning a pointer + ** the same number of characters into the UTF-16 string. + */ + int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8); + *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed); + } + sqlite3_free(zSql8); + rc = sqlite3ApiExit(db, rc); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** Two versions of the official API. Legacy and new use. In the legacy +** version, the original SQL text is not saved in the prepared statement +** and so if a schema change occurs, SQLITE_SCHEMA is returned by +** sqlite3_step(). In the new version, the original SQL text is retained +** and the statement is automatically recompiled if an schema change +** occurs. +*/ +int sqlite3_prepare16( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + return sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail); +} +int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle. */ + const void *zSql, /* UTF-8 encoded SQL statement. */ + int nBytes, /* Length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ + const void **pzTail /* OUT: End of parsed string */ +){ + return sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail); +} + +#endif /* SQLITE_OMIT_UTF16 */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/printf.c b/client/src/thirdparty/sqlite-3.4.2/src/printf.c new file mode 100644 index 0000000..eafe842 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/printf.c @@ -0,0 +1,904 @@ +/* +** The "printf" code that follows dates from the 1980's. It is in +** the public domain. The original comments are included here for +** completeness. They are very out-of-date but might be useful as +** an historical reference. Most of the "enhancements" have been backed +** out so that the functionality is now the same as standard printf(). +** +************************************************************************** +** +** The following modules is an enhanced replacement for the "printf" subroutines +** found in the standard C library. The following enhancements are +** supported: +** +** + Additional functions. The standard set of "printf" functions +** includes printf, fprintf, sprintf, vprintf, vfprintf, and +** vsprintf. This module adds the following: +** +** * snprintf -- Works like sprintf, but has an extra argument +** which is the size of the buffer written to. +** +** * mprintf -- Similar to sprintf. Writes output to memory +** obtained from malloc. +** +** * xprintf -- Calls a function to dispose of output. +** +** * nprintf -- No output, but returns the number of characters +** that would have been output by printf. +** +** * A v- version (ex: vsnprintf) of every function is also +** supplied. +** +** + A few extensions to the formatting notation are supported: +** +** * The "=" flag (similar to "-") causes the output to be +** be centered in the appropriately sized field. +** +** * The %b field outputs an integer in binary notation. +** +** * The %c field now accepts a precision. The character output +** is repeated by the number of times the precision specifies. +** +** * The %' field works like %c, but takes as its character the +** next character of the format string, instead of the next +** argument. For example, printf("%.78'-") prints 78 minus +** signs, the same as printf("%.78c",'-'). +** +** + When compiled using GCC on a SPARC, this version of printf is +** faster than the library printf for SUN OS 4.1. +** +** + All functions are fully reentrant. +** +*/ +#include "sqliteInt.h" + +/* +** Conversion types fall into various categories as defined by the +** following enumeration. +*/ +#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ +#define etFLOAT 2 /* Floating point. %f */ +#define etEXP 3 /* Exponentional notation. %e and %E */ +#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ +#define etSIZE 5 /* Return number of characters processed so far. %n */ +#define etSTRING 6 /* Strings. %s */ +#define etDYNSTRING 7 /* Dynamically allocated strings. %z */ +#define etPERCENT 8 /* Percent symbol. %% */ +#define etCHARX 9 /* Characters. %c */ +/* The rest are extensions, not normally found in printf() */ +#define etCHARLIT 10 /* Literal characters. %' */ +#define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */ +#define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '', + NULL pointers replaced by SQL NULL. %Q */ +#define etTOKEN 13 /* a pointer to a Token structure */ +#define etSRCLIST 14 /* a pointer to a SrcList */ +#define etPOINTER 15 /* The %p conversion */ +#define etSQLESCAPE3 16 /* %w -> Strings with '\"' doubled */ +#define etORDINAL 17 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ + + +/* +** An "etByte" is an 8-bit unsigned value. +*/ +typedef unsigned char etByte; + +/* +** Each builtin conversion character (ex: the 'd' in "%d") is described +** by an instance of the following structure +*/ +typedef struct et_info { /* Information about each format field */ + char fmttype; /* The format field code letter */ + etByte base; /* The base for radix conversion */ + etByte flags; /* One or more of FLAG_ constants below */ + etByte type; /* Conversion paradigm */ + etByte charset; /* Offset into aDigits[] of the digits string */ + etByte prefix; /* Offset into aPrefix[] of the prefix string */ +} et_info; + +/* +** Allowed values for et_info.flags +*/ +#define FLAG_SIGNED 1 /* True if the value to convert is signed */ +#define FLAG_INTERN 2 /* True if for internal use only */ +#define FLAG_STRING 4 /* Allow infinity precision */ + + +/* +** The following table is searched linearly, so it is good to put the +** most frequently used conversion types first. +*/ +static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; +static const char aPrefix[] = "-x0\000X0"; +static const et_info fmtinfo[] = { + { 'd', 10, 1, etRADIX, 0, 0 }, + { 's', 0, 4, etSTRING, 0, 0 }, + { 'g', 0, 1, etGENERIC, 30, 0 }, + { 'z', 0, 4, etDYNSTRING, 0, 0 }, + { 'q', 0, 4, etSQLESCAPE, 0, 0 }, + { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, + { 'w', 0, 4, etSQLESCAPE3, 0, 0 }, + { 'c', 0, 0, etCHARX, 0, 0 }, + { 'o', 8, 0, etRADIX, 0, 2 }, + { 'u', 10, 0, etRADIX, 0, 0 }, + { 'x', 16, 0, etRADIX, 16, 1 }, + { 'X', 16, 0, etRADIX, 0, 4 }, +#ifndef SQLITE_OMIT_FLOATING_POINT + { 'f', 0, 1, etFLOAT, 0, 0 }, + { 'e', 0, 1, etEXP, 30, 0 }, + { 'E', 0, 1, etEXP, 14, 0 }, + { 'G', 0, 1, etGENERIC, 14, 0 }, +#endif + { 'i', 10, 1, etRADIX, 0, 0 }, + { 'n', 0, 0, etSIZE, 0, 0 }, + { '%', 0, 0, etPERCENT, 0, 0 }, + { 'p', 16, 0, etPOINTER, 0, 1 }, + { 'T', 0, 2, etTOKEN, 0, 0 }, + { 'S', 0, 2, etSRCLIST, 0, 0 }, + { 'r', 10, 3, etORDINAL, 0, 0 }, +}; +#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) + +/* +** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point +** conversions will work. +*/ +#ifndef SQLITE_OMIT_FLOATING_POINT +/* +** "*val" is a double such that 0.1 <= *val < 10.0 +** Return the ascii code for the leading digit of *val, then +** multiply "*val" by 10.0 to renormalize. +** +** Example: +** input: *val = 3.14159 +** output: *val = 1.4159 function return = '3' +** +** The counter *cnt is incremented each time. After counter exceeds +** 16 (the number of significant digits in a 64-bit float) '0' is +** always returned. +*/ +static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ + int digit; + LONGDOUBLE_TYPE d; + if( (*cnt)++ >= 16 ) return '0'; + digit = (int)*val; + d = digit; + digit += '0'; + *val = (*val - d)*10.0; + return digit; +} +#endif /* SQLITE_OMIT_FLOATING_POINT */ + +/* +** Append N space characters to the given string buffer. +*/ +static void appendSpace(StrAccum *pAccum, int N){ + static const char zSpaces[] = " "; + while( N>=sizeof(zSpaces)-1 ){ + sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1); + N -= sizeof(zSpaces)-1; + } + if( N>0 ){ + sqlite3StrAccumAppend(pAccum, zSpaces, N); + } +} + +/* +** On machines with a small stack size, you can redefine the +** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for +** smaller values some %f conversions may go into an infinite loop. +*/ +#ifndef SQLITE_PRINT_BUF_SIZE +# define SQLITE_PRINT_BUF_SIZE 350 +#endif +#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */ + +/* +** The root program. All variations call this core. +** +** INPUTS: +** func This is a pointer to a function taking three arguments +** 1. A pointer to anything. Same as the "arg" parameter. +** 2. A pointer to the list of characters to be output +** (Note, this list is NOT null terminated.) +** 3. An integer number of characters to be output. +** (Note: This number might be zero.) +** +** arg This is the pointer to anything which will be passed as the +** first argument to "func". Use it for whatever you like. +** +** fmt This is the format string, as in the usual print. +** +** ap This is a pointer to a list of arguments. Same as in +** vfprint. +** +** OUTPUTS: +** The return value is the total number of characters sent to +** the function "func". Returns -1 on a error. +** +** Note that the order in which automatic variables are declared below +** seems to make a big difference in determining how fast this beast +** will run. +*/ +static void vxprintf( + StrAccum *pAccum, /* Accumulate results here */ + int useExtended, /* Allow extended %-conversions */ + const char *fmt, /* Format string */ + va_list ap /* arguments */ +){ + int c; /* Next character in the format string */ + char *bufpt; /* Pointer to the conversion buffer */ + int precision; /* Precision of the current field */ + int length; /* Length of the field */ + int idx; /* A general purpose loop counter */ + int width; /* Width of the current field */ + etByte flag_leftjustify; /* True if "-" flag is present */ + etByte flag_plussign; /* True if "+" flag is present */ + etByte flag_blanksign; /* True if " " flag is present */ + etByte flag_alternateform; /* True if "#" flag is present */ + etByte flag_altform2; /* True if "!" flag is present */ + etByte flag_zeropad; /* True if field width constant starts with zero */ + etByte flag_long; /* True if "l" flag is present */ + etByte flag_longlong; /* True if the "ll" flag is present */ + etByte done; /* Loop termination flag */ + sqlite_uint64 longvalue; /* Value for integer types */ + LONGDOUBLE_TYPE realvalue; /* Value for real types */ + const et_info *infop; /* Pointer to the appropriate info structure */ + char buf[etBUFSIZE]; /* Conversion buffer */ + char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ + etByte errorflag = 0; /* True if an error is encountered */ + etByte xtype; /* Conversion paradigm */ + char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ +#ifndef SQLITE_OMIT_FLOATING_POINT + int exp, e2; /* exponent of real numbers */ + double rounder; /* Used for rounding floating point values */ + etByte flag_dp; /* True if decimal point should be shown */ + etByte flag_rtz; /* True if trailing zeros should be removed */ + etByte flag_exp; /* True to force display of the exponent */ + int nsd; /* Number of significant digits returned */ +#endif + + length = 0; + bufpt = 0; + for(; (c=(*fmt))!=0; ++fmt){ + if( c!='%' ){ + int amt; + bufpt = (char *)fmt; + amt = 1; + while( (c=(*++fmt))!='%' && c!=0 ) amt++; + sqlite3StrAccumAppend(pAccum, bufpt, amt); + if( c==0 ) break; + } + if( (c=(*++fmt))==0 ){ + errorflag = 1; + sqlite3StrAccumAppend(pAccum, "%", 1); + break; + } + /* Find out what flags are present */ + flag_leftjustify = flag_plussign = flag_blanksign = + flag_alternateform = flag_altform2 = flag_zeropad = 0; + done = 0; + do{ + switch( c ){ + case '-': flag_leftjustify = 1; break; + case '+': flag_plussign = 1; break; + case ' ': flag_blanksign = 1; break; + case '#': flag_alternateform = 1; break; + case '!': flag_altform2 = 1; break; + case '0': flag_zeropad = 1; break; + default: done = 1; break; + } + }while( !done && (c=(*++fmt))!=0 ); + /* Get the field width */ + width = 0; + if( c=='*' ){ + width = va_arg(ap,int); + if( width<0 ){ + flag_leftjustify = 1; + width = -width; + } + c = *++fmt; + }else{ + while( c>='0' && c<='9' ){ + width = width*10 + c - '0'; + c = *++fmt; + } + } + if( width > etBUFSIZE-10 ){ + width = etBUFSIZE-10; + } + /* Get the precision */ + if( c=='.' ){ + precision = 0; + c = *++fmt; + if( c=='*' ){ + precision = va_arg(ap,int); + if( precision<0 ) precision = -precision; + c = *++fmt; + }else{ + while( c>='0' && c<='9' ){ + precision = precision*10 + c - '0'; + c = *++fmt; + } + } + }else{ + precision = -1; + } + /* Get the conversion type modifier */ + if( c=='l' ){ + flag_long = 1; + c = *++fmt; + if( c=='l' ){ + flag_longlong = 1; + c = *++fmt; + }else{ + flag_longlong = 0; + } + }else{ + flag_long = flag_longlong = 0; + } + /* Fetch the info entry for the field */ + infop = 0; + for(idx=0; idxflags & FLAG_INTERN)==0 ){ + xtype = infop->type; + }else{ + return; + } + break; + } + } + zExtra = 0; + if( infop==0 ){ + return; + } + + + /* Limit the precision to prevent overflowing buf[] during conversion */ + if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){ + precision = etBUFSIZE-40; + } + + /* + ** At this point, variables are initialized as follows: + ** + ** flag_alternateform TRUE if a '#' is present. + ** flag_altform2 TRUE if a '!' is present. + ** flag_plussign TRUE if a '+' is present. + ** flag_leftjustify TRUE if a '-' is present or if the + ** field width was negative. + ** flag_zeropad TRUE if the width began with 0. + ** flag_long TRUE if the letter 'l' (ell) prefixed + ** the conversion character. + ** flag_longlong TRUE if the letter 'll' (ell ell) prefixed + ** the conversion character. + ** flag_blanksign TRUE if a ' ' is present. + ** width The specified field width. This is + ** always non-negative. Zero is the default. + ** precision The specified precision. The default + ** is -1. + ** xtype The class of the conversion. + ** infop Pointer to the appropriate info struct. + */ + switch( xtype ){ + case etPOINTER: + flag_longlong = sizeof(char*)==sizeof(i64); + flag_long = sizeof(char*)==sizeof(long int); + /* Fall through into the next case */ + case etORDINAL: + case etRADIX: + if( infop->flags & FLAG_SIGNED ){ + i64 v; + if( flag_longlong ) v = va_arg(ap,i64); + else if( flag_long ) v = va_arg(ap,long int); + else v = va_arg(ap,int); + if( v<0 ){ + longvalue = -v; + prefix = '-'; + }else{ + longvalue = v; + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; + } + }else{ + if( flag_longlong ) longvalue = va_arg(ap,u64); + else if( flag_long ) longvalue = va_arg(ap,unsigned long int); + else longvalue = va_arg(ap,unsigned int); + prefix = 0; + } + if( longvalue==0 ) flag_alternateform = 0; + if( flag_zeropad && precision=4 || (longvalue/10)%10==1 ){ + x = 0; + } + buf[etBUFSIZE-3] = zOrd[x*2]; + buf[etBUFSIZE-2] = zOrd[x*2+1]; + bufpt -= 2; + } + { + register const char *cset; /* Use registers for speed */ + register int base; + cset = &aDigits[infop->charset]; + base = infop->base; + do{ /* Convert to ascii */ + *(--bufpt) = cset[longvalue%base]; + longvalue = longvalue/base; + }while( longvalue>0 ); + } + length = &buf[etBUFSIZE-1]-bufpt; + for(idx=precision-length; idx>0; idx--){ + *(--bufpt) = '0'; /* Zero pad */ + } + if( prefix ) *(--bufpt) = prefix; /* Add sign */ + if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ + const char *pre; + char x; + pre = &aPrefix[infop->prefix]; + if( *bufpt!=pre[0] ){ + for(; (x=(*pre))!=0; pre++) *(--bufpt) = x; + } + } + length = &buf[etBUFSIZE-1]-bufpt; + break; + case etFLOAT: + case etEXP: + case etGENERIC: + realvalue = va_arg(ap,double); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( precision<0 ) precision = 6; /* Set default precision */ + if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10; + if( realvalue<0.0 ){ + realvalue = -realvalue; + prefix = '-'; + }else{ + if( flag_plussign ) prefix = '+'; + else if( flag_blanksign ) prefix = ' '; + else prefix = 0; + } + if( xtype==etGENERIC && precision>0 ) precision--; +#if 0 + /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */ + for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); +#else + /* It makes more sense to use 0.5 */ + for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){} +#endif + if( xtype==etFLOAT ) realvalue += rounder; + /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ + exp = 0; + if( sqlite3_isnan(realvalue) ){ + bufpt = "NaN"; + length = 3; + break; + } + if( realvalue>0.0 ){ + while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; } + while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } + while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } + while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; } + while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } + if( exp>350 || exp<-350 ){ + if( prefix=='-' ){ + bufpt = "-Inf"; + }else if( prefix=='+' ){ + bufpt = "+Inf"; + }else{ + bufpt = "Inf"; + } + length = strlen(bufpt); + break; + } + } + bufpt = buf; + /* + ** If the field type is etGENERIC, then convert to either etEXP + ** or etFLOAT, as appropriate. + */ + flag_exp = xtype==etEXP; + if( xtype!=etFLOAT ){ + realvalue += rounder; + if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } + } + if( xtype==etGENERIC ){ + flag_rtz = !flag_alternateform; + if( exp<-4 || exp>precision ){ + xtype = etEXP; + }else{ + precision = precision - exp; + xtype = etFLOAT; + } + }else{ + flag_rtz = 0; + } + if( xtype==etEXP ){ + e2 = 0; + }else{ + e2 = exp; + } + nsd = 0; + flag_dp = (precision>0) | flag_alternateform | flag_altform2; + /* The sign in front of the number */ + if( prefix ){ + *(bufpt++) = prefix; + } + /* Digits prior to the decimal point */ + if( e2<0 ){ + *(bufpt++) = '0'; + }else{ + for(; e2>=0; e2--){ + *(bufpt++) = et_getdigit(&realvalue,&nsd); + } + } + /* The decimal point */ + if( flag_dp ){ + *(bufpt++) = '.'; + } + /* "0" digits after the decimal point but before the first + ** significant digit of the number */ + for(e2++; e2<0 && precision>0; precision--, e2++){ + *(bufpt++) = '0'; + } + /* Significant digits after the decimal point */ + while( (precision--)>0 ){ + *(bufpt++) = et_getdigit(&realvalue,&nsd); + } + /* Remove trailing zeros and the "." if no digits follow the "." */ + if( flag_rtz && flag_dp ){ + while( bufpt[-1]=='0' ) *(--bufpt) = 0; + assert( bufpt>buf ); + if( bufpt[-1]=='.' ){ + if( flag_altform2 ){ + *(bufpt++) = '0'; + }else{ + *(--bufpt) = 0; + } + } + } + /* Add the "eNNN" suffix */ + if( flag_exp || (xtype==etEXP && exp) ){ + *(bufpt++) = aDigits[infop->charset]; + if( exp<0 ){ + *(bufpt++) = '-'; exp = -exp; + }else{ + *(bufpt++) = '+'; + } + if( exp>=100 ){ + *(bufpt++) = (exp/100)+'0'; /* 100's digit */ + exp %= 100; + } + *(bufpt++) = exp/10+'0'; /* 10's digit */ + *(bufpt++) = exp%10+'0'; /* 1's digit */ + } + *bufpt = 0; + + /* The converted number is in buf[] and zero terminated. Output it. + ** Note that the number is in the usual order, not reversed as with + ** integer conversions. */ + length = bufpt-buf; + bufpt = buf; + + /* Special case: Add leading zeros if the flag_zeropad flag is + ** set and we are not left justified */ + if( flag_zeropad && !flag_leftjustify && length < width){ + int i; + int nPad = width - length; + for(i=width; i>=nPad; i--){ + bufpt[i] = bufpt[i-nPad]; + } + i = prefix!=0; + while( nPad-- ) bufpt[i++] = '0'; + length = width; + } +#endif + break; + case etSIZE: + *(va_arg(ap,int*)) = pAccum->nChar; + length = width = 0; + break; + case etPERCENT: + buf[0] = '%'; + bufpt = buf; + length = 1; + break; + case etCHARLIT: + case etCHARX: + c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt); + if( precision>=0 ){ + for(idx=1; idx=0 && precisionetBUFSIZE ){ + bufpt = zExtra = sqlite3_malloc( n ); + if( bufpt==0 ) return; + }else{ + bufpt = buf; + } + j = 0; + if( needQuote ) bufpt[j++] = q; + for(i=0; (ch=escarg[i])!=0; i++){ + bufpt[j++] = ch; + if( ch==q ) bufpt[j++] = ch; + } + if( needQuote ) bufpt[j++] = q; + bufpt[j] = 0; + length = j; + /* The precision is ignored on %q and %Q */ + /* if( precision>=0 && precisionz ){ + sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n); + } + length = width = 0; + break; + } + case etSRCLIST: { + SrcList *pSrc = va_arg(ap, SrcList*); + int k = va_arg(ap, int); + struct SrcList_item *pItem = &pSrc->a[k]; + assert( k>=0 && knSrc ); + if( pItem->zDatabase && pItem->zDatabase[0] ){ + sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1); + sqlite3StrAccumAppend(pAccum, ".", 1); + } + sqlite3StrAccumAppend(pAccum, pItem->zName, -1); + length = width = 0; + break; + } + }/* End switch over the format type */ + /* + ** The text of the conversion is pointed to by "bufpt" and is + ** "length" characters long. The field width is "width". Do + ** the output. + */ + if( !flag_leftjustify ){ + register int nspace; + nspace = width-length; + if( nspace>0 ){ + appendSpace(pAccum, nspace); + } + } + if( length>0 ){ + sqlite3StrAccumAppend(pAccum, bufpt, length); + } + if( flag_leftjustify ){ + register int nspace; + nspace = width-length; + if( nspace>0 ){ + appendSpace(pAccum, nspace); + } + } + if( zExtra ){ + sqlite3_free(zExtra); + } + }/* End for loop over the format string */ +} /* End of function */ + +/* +** Append N bytes of text from z to the StrAccum object. +*/ +void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){ + if( p->tooBig | p->mallocFailed ){ + return; + } + if( N<0 ){ + N = strlen(z); + } + if( N==0 ){ + return; + } + if( p->nChar+N >= p->nAlloc ){ + char *zNew; + if( !p->useMalloc ){ + p->tooBig = 1; + N = p->nAlloc - p->nChar - 1; + if( N<=0 ){ + return; + } + }else{ + p->nAlloc += p->nAlloc + N + 1; + if( p->nAlloc > SQLITE_MAX_LENGTH ){ + p->nAlloc = SQLITE_MAX_LENGTH; + if( p->nChar+N >= p->nAlloc ){ + sqlite3StrAccumReset(p); + p->tooBig = 1; + return; + } + } + zNew = sqlite3_malloc( p->nAlloc ); + if( zNew ){ + memcpy(zNew, p->zText, p->nChar); + sqlite3StrAccumReset(p); + p->zText = zNew; + }else{ + p->mallocFailed = 1; + sqlite3StrAccumReset(p); + return; + } + } + } + memcpy(&p->zText[p->nChar], z, N); + p->nChar += N; +} + +/* +** Finish off a string by making sure it is zero-terminated. +** Return a pointer to the resulting string. Return a NULL +** pointer if any kind of error was encountered. +*/ +char *sqlite3StrAccumFinish(StrAccum *p){ + if( p->zText ){ + p->zText[p->nChar] = 0; + if( p->useMalloc && p->zText==p->zBase ){ + p->zText = sqlite3_malloc( p->nChar+1 ); + if( p->zText ){ + memcpy(p->zText, p->zBase, p->nChar+1); + }else{ + p->mallocFailed = 1; + } + } + } + return p->zText; +} + +/* +** Reset an StrAccum string. Reclaim all malloced memory. +*/ +void sqlite3StrAccumReset(StrAccum *p){ + if( p->zText!=p->zBase ){ + sqlite3_free(p->zText); + p->zText = 0; + } +} + +/* +** Initialize a string accumulator +*/ +static void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n){ + p->zText = p->zBase = zBase; + p->nChar = 0; + p->nAlloc = n; + p->useMalloc = 1; + p->tooBig = 0; + p->mallocFailed = 0; +} + +/* +** Print into memory obtained from sqliteMalloc(). Use the internal +** %-conversion extensions. +*/ +char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){ + char *z; + char zBase[SQLITE_PRINT_BUF_SIZE]; + StrAccum acc; + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase)); + vxprintf(&acc, 1, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + if( acc.mallocFailed && db ){ + db->mallocFailed = 1; + } + return z; +} + +/* +** Print into memory obtained from sqliteMalloc(). Use the internal +** %-conversion extensions. +*/ +char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3VMPrintf(db, zFormat, ap); + va_end(ap); + return z; +} + +/* +** Print into memory obtained from sqlite3_malloc(). Omit the internal +** %-conversion extensions. +*/ +char *sqlite3_vmprintf(const char *zFormat, va_list ap){ + char *z; + char zBase[SQLITE_PRINT_BUF_SIZE]; + StrAccum acc; + sqlite3StrAccumInit(&acc, zBase, sizeof(zBase)); + vxprintf(&acc, 0, zFormat, ap); + z = sqlite3StrAccumFinish(&acc); + return z; +} + +/* +** Print into memory obtained from sqlite3_malloc()(). Omit the internal +** %-conversion extensions. +*/ +char *sqlite3_mprintf(const char *zFormat, ...){ + va_list ap; + char *z; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + return z; +} + +/* +** sqlite3_snprintf() works like snprintf() except that it ignores the +** current locale settings. This is important for SQLite because we +** are not able to use a "," as the decimal point in place of "." as +** specified by some locales. +*/ +char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ + char *z; + va_list ap; + StrAccum acc; + + if( n<=0 ){ + return zBuf; + } + sqlite3StrAccumInit(&acc, zBuf, n); + acc.useMalloc = 0; + va_start(ap,zFormat); + vxprintf(&acc, 0, zFormat, ap); + va_end(ap); + z = sqlite3StrAccumFinish(&acc); + return z; +} + +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) || defined(SQLITE_MEMDEBUG) +/* +** A version of printf() that understands %lld. Used for debugging. +** The printf() built into some versions of windows does not understand %lld +** and segfaults if you give it a long long int. +*/ +void sqlite3DebugPrintf(const char *zFormat, ...){ + va_list ap; + StrAccum acc; + char zBuf[500]; + sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf)); + acc.useMalloc = 0; + va_start(ap,zFormat); + vxprintf(&acc, 0, zFormat, ap); + va_end(ap); + sqlite3StrAccumFinish(&acc); + fprintf(stdout,"%s", zBuf); + fflush(stdout); +} +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/random.c b/client/src/thirdparty/sqlite-3.4.2/src/random.c new file mode 100644 index 0000000..8684ce6 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/random.c @@ -0,0 +1,121 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains code to implement a pseudo-random number +** generator (PRNG) for SQLite. +** +** Random numbers are used by some of the database backends in order +** to generate random integer keys for tables or random filenames. +** +** $Id: random.c,v 1.21 2008/01/16 17:46:38 drh Exp $ +*/ +#include "sqliteInt.h" + + +/* All threads share a single random number generator. +** This structure is the current state of the generator. +*/ +static struct sqlite3PrngType { + unsigned char isInit; /* True if initialized */ + unsigned char i, j; /* State variables */ + unsigned char s[256]; /* State variables */ +} sqlite3Prng; + +/* +** Get a single 8-bit random value from the RC4 PRNG. The Mutex +** must be held while executing this routine. +** +** Why not just use a library random generator like lrand48() for this? +** Because the OP_NewRowid opcode in the VDBE depends on having a very +** good source of random numbers. The lrand48() library function may +** well be good enough. But maybe not. Or maybe lrand48() has some +** subtle problems on some systems that could cause problems. It is hard +** to know. To minimize the risk of problems due to bad lrand48() +** implementations, SQLite uses this random number generator based +** on RC4, which we know works very well. +** +** (Later): Actually, OP_NewRowid does not depend on a good source of +** randomness any more. But we will leave this code in all the same. +*/ +static int randomByte(void){ + unsigned char t; + + + /* Initialize the state of the random number generator once, + ** the first time this routine is called. The seed value does + ** not need to contain a lot of randomness since we are not + ** trying to do secure encryption or anything like that... + ** + ** Nothing in this file or anywhere else in SQLite does any kind of + ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random + ** number generator) not as an encryption device. + */ + if( !sqlite3Prng.isInit ){ + int i; + char k[256]; + sqlite3Prng.j = 0; + sqlite3Prng.i = 0; + sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k); + for(i=0; i<256; i++){ + sqlite3Prng.s[i] = i; + } + for(i=0; i<256; i++){ + sqlite3Prng.j += sqlite3Prng.s[i] + k[i]; + t = sqlite3Prng.s[sqlite3Prng.j]; + sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i]; + sqlite3Prng.s[i] = t; + } + sqlite3Prng.isInit = 1; + } + + /* Generate and return single random byte + */ + sqlite3Prng.i++; + t = sqlite3Prng.s[sqlite3Prng.i]; + sqlite3Prng.j += t; + sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j]; + sqlite3Prng.s[sqlite3Prng.j] = t; + t += sqlite3Prng.s[sqlite3Prng.i]; + return sqlite3Prng.s[t]; +} + +/* +** Return N random bytes. +*/ +void sqlite3Randomness(int N, void *pBuf){ + unsigned char *zBuf = pBuf; + static sqlite3_mutex *mutex = 0; + if( mutex==0 ){ + mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG); + } + sqlite3_mutex_enter(mutex); + while( N-- ){ + *(zBuf++) = randomByte(); + } + sqlite3_mutex_leave(mutex); +} + +#ifdef SQLITE_TEST +/* +** For testing purposes, we sometimes want to preserve the state of +** PRNG and restore the PRNG to its saved state at a later time. +*/ +static struct sqlite3PrngType sqlite3SavedPrng; +void sqlite3SavePrngState(void){ + memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng)); +} +void sqlite3RestorePrngState(void){ + memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng)); +} +void sqlite3ResetPrngState(void){ + sqlite3Prng.isInit = 0; +} +#endif /* SQLITE_TEST */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/select.c b/client/src/thirdparty/sqlite-3.4.2/src/select.c new file mode 100644 index 0000000..981691f --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/select.c @@ -0,0 +1,3705 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains C code routines that are called by the parser +** to handle SELECT statements in SQLite. +** +** $Id: select.c,v 1.411 2008/01/25 15:04:50 drh Exp $ +*/ +#include "sqliteInt.h" + + +/* +** Delete all the content of a Select structure but do not deallocate +** the select structure itself. +*/ +static void clearSelect(Select *p){ + sqlite3ExprListDelete(p->pEList); + sqlite3SrcListDelete(p->pSrc); + sqlite3ExprDelete(p->pWhere); + sqlite3ExprListDelete(p->pGroupBy); + sqlite3ExprDelete(p->pHaving); + sqlite3ExprListDelete(p->pOrderBy); + sqlite3SelectDelete(p->pPrior); + sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(p->pOffset); +} + +/* +** Initialize a SelectDest structure. +*/ +void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ + pDest->eDest = eDest; + pDest->iParm = iParm; + pDest->affinity = 0; + pDest->iMem = 0; +} + + +/* +** Allocate a new Select structure and return a pointer to that +** structure. +*/ +Select *sqlite3SelectNew( + Parse *pParse, /* Parsing context */ + ExprList *pEList, /* which columns to include in the result */ + SrcList *pSrc, /* the FROM clause -- which tables to scan */ + Expr *pWhere, /* the WHERE clause */ + ExprList *pGroupBy, /* the GROUP BY clause */ + Expr *pHaving, /* the HAVING clause */ + ExprList *pOrderBy, /* the ORDER BY clause */ + int isDistinct, /* true if the DISTINCT keyword is present */ + Expr *pLimit, /* LIMIT value. NULL means not used */ + Expr *pOffset /* OFFSET value. NULL means no offset */ +){ + Select *pNew; + Select standin; + sqlite3 *db = pParse->db; + pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); + assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */ + if( pNew==0 ){ + pNew = &standin; + memset(pNew, 0, sizeof(*pNew)); + } + if( pEList==0 ){ + pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0); + } + pNew->pEList = pEList; + pNew->pSrc = pSrc; + pNew->pWhere = pWhere; + pNew->pGroupBy = pGroupBy; + pNew->pHaving = pHaving; + pNew->pOrderBy = pOrderBy; + pNew->isDistinct = isDistinct; + pNew->op = TK_SELECT; + assert( pOffset==0 || pLimit!=0 ); + pNew->pLimit = pLimit; + pNew->pOffset = pOffset; + pNew->iLimit = -1; + pNew->iOffset = -1; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + if( pNew==&standin) { + clearSelect(pNew); + pNew = 0; + } + return pNew; +} + +/* +** Delete the given Select structure and all of its substructures. +*/ +void sqlite3SelectDelete(Select *p){ + if( p ){ + clearSelect(p); + sqlite3_free(p); + } +} + +/* +** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the +** type of join. Return an integer constant that expresses that type +** in terms of the following bit values: +** +** JT_INNER +** JT_CROSS +** JT_OUTER +** JT_NATURAL +** JT_LEFT +** JT_RIGHT +** +** A full outer join is the combination of JT_LEFT and JT_RIGHT. +** +** If an illegal or unsupported join type is seen, then still return +** a join type, but put an error in the pParse structure. +*/ +int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ + int jointype = 0; + Token *apAll[3]; + Token *p; + static const struct { + const char zKeyword[8]; + u8 nChar; + u8 code; + } keywords[] = { + { "natural", 7, JT_NATURAL }, + { "left", 4, JT_LEFT|JT_OUTER }, + { "right", 5, JT_RIGHT|JT_OUTER }, + { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + { "outer", 5, JT_OUTER }, + { "inner", 5, JT_INNER }, + { "cross", 5, JT_INNER|JT_CROSS }, + }; + int i, j; + apAll[0] = pA; + apAll[1] = pB; + apAll[2] = pC; + for(i=0; i<3 && apAll[i]; i++){ + p = apAll[i]; + for(j=0; jn==keywords[j].nChar + && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ + jointype |= keywords[j].code; + break; + } + } + if( j>=sizeof(keywords)/sizeof(keywords[0]) ){ + jointype |= JT_ERROR; + break; + } + } + if( + (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || + (jointype & JT_ERROR)!=0 + ){ + const char *zSp1 = " "; + const char *zSp2 = " "; + if( pB==0 ){ zSp1++; } + if( pC==0 ){ zSp2++; } + sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " + "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC); + jointype = JT_INNER; + }else if( jointype & JT_RIGHT ){ + sqlite3ErrorMsg(pParse, + "RIGHT and FULL OUTER JOINs are not currently supported"); + jointype = JT_INNER; + } + return jointype; +} + +/* +** Return the index of a column in a table. Return -1 if the column +** is not contained in the table. +*/ +static int columnIndex(Table *pTab, const char *zCol){ + int i; + for(i=0; inCol; i++){ + if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i; + } + return -1; +} + +/* +** Set the value of a token to a '\000'-terminated string. +*/ +static void setToken(Token *p, const char *z){ + p->z = (u8*)z; + p->n = z ? strlen(z) : 0; + p->dyn = 0; +} + +/* +** Set the token to the double-quoted and escaped version of the string pointed +** to by z. For example; +** +** {a"bc} -> {"a""bc"} +*/ +static void setQuotedToken(Parse *pParse, Token *p, const char *z){ + p->z = (u8 *)sqlite3MPrintf(0, "\"%w\"", z); + p->dyn = 1; + if( p->z ){ + p->n = strlen((char *)p->z); + }else{ + pParse->db->mallocFailed = 1; + } +} + +/* +** Create an expression node for an identifier with the name of zName +*/ +Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){ + Token dummy; + setToken(&dummy, zName); + return sqlite3PExpr(pParse, TK_ID, 0, 0, &dummy); +} + + +/* +** Add a term to the WHERE expression in *ppExpr that requires the +** zCol column to be equal in the two tables pTab1 and pTab2. +*/ +static void addWhereTerm( + Parse *pParse, /* Parsing context */ + const char *zCol, /* Name of the column */ + const Table *pTab1, /* First table */ + const char *zAlias1, /* Alias for first table. May be NULL */ + const Table *pTab2, /* Second table */ + const char *zAlias2, /* Alias for second table. May be NULL */ + int iRightJoinTable, /* VDBE cursor for the right table */ + Expr **ppExpr /* Add the equality term to this expression */ +){ + Expr *pE1a, *pE1b, *pE1c; + Expr *pE2a, *pE2b, *pE2c; + Expr *pE; + + pE1a = sqlite3CreateIdExpr(pParse, zCol); + pE2a = sqlite3CreateIdExpr(pParse, zCol); + if( zAlias1==0 ){ + zAlias1 = pTab1->zName; + } + pE1b = sqlite3CreateIdExpr(pParse, zAlias1); + if( zAlias2==0 ){ + zAlias2 = pTab2->zName; + } + pE2b = sqlite3CreateIdExpr(pParse, zAlias2); + pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0); + pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0); + pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0); + if( pE ){ + ExprSetProperty(pE, EP_FromJoin); + pE->iRightJoinTable = iRightJoinTable; + } + *ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE); +} + +/* +** Set the EP_FromJoin property on all terms of the given expression. +** And set the Expr.iRightJoinTable to iTable for every term in the +** expression. +** +** The EP_FromJoin property is used on terms of an expression to tell +** the LEFT OUTER JOIN processing logic that this term is part of the +** join restriction specified in the ON or USING clause and not a part +** of the more general WHERE clause. These terms are moved over to the +** WHERE clause during join processing but we need to remember that they +** originated in the ON or USING clause. +** +** The Expr.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table iRightJoinTable even if that table is not +** explicitly mentioned in the expression. That information is needed +** for cases like this: +** +** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 +** +** The where clause needs to defer the handling of the t1.x=5 +** term until after the t2 loop of the join. In that way, a +** NULL t2 row will be inserted whenever t1.x!=5. If we do not +** defer the handling of t1.x=5, it will be processed immediately +** after the t1 loop and rows with t1.x!=5 will never appear in +** the output, which is incorrect. +*/ +static void setJoinExpr(Expr *p, int iTable){ + while( p ){ + ExprSetProperty(p, EP_FromJoin); + p->iRightJoinTable = iTable; + setJoinExpr(p->pLeft, iTable); + p = p->pRight; + } +} + +/* +** This routine processes the join information for a SELECT statement. +** ON and USING clauses are converted into extra terms of the WHERE clause. +** NATURAL joins also create extra WHERE clause terms. +** +** The terms of a FROM clause are contained in the Select.pSrc structure. +** The left most table is the first entry in Select.pSrc. The right-most +** table is the last entry. The join operator is held in the entry to +** the left. Thus entry 0 contains the join operator for the join between +** entries 0 and 1. Any ON or USING clauses associated with the join are +** also attached to the left entry. +** +** This routine returns the number of errors encountered. +*/ +static int sqliteProcessJoin(Parse *pParse, Select *p){ + SrcList *pSrc; /* All tables in the FROM clause */ + int i, j; /* Loop counters */ + struct SrcList_item *pLeft; /* Left table being joined */ + struct SrcList_item *pRight; /* Right table being joined */ + + pSrc = p->pSrc; + pLeft = &pSrc->a[0]; + pRight = &pLeft[1]; + for(i=0; inSrc-1; i++, pRight++, pLeft++){ + Table *pLeftTab = pLeft->pTab; + Table *pRightTab = pRight->pTab; + + if( pLeftTab==0 || pRightTab==0 ) continue; + + /* When the NATURAL keyword is present, add WHERE clause terms for + ** every column that the two tables have in common. + */ + if( pRight->jointype & JT_NATURAL ){ + if( pRight->pOn || pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "a NATURAL join may not have " + "an ON or USING clause", 0); + return 1; + } + for(j=0; jnCol; j++){ + char *zName = pLeftTab->aCol[j].zName; + if( columnIndex(pRightTab, zName)>=0 ){ + addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere); + + } + } + } + + /* Disallow both ON and USING clauses in the same join + */ + if( pRight->pOn && pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "cannot have both ON and USING " + "clauses in the same join"); + return 1; + } + + /* Add the ON clause to the end of the WHERE clause, connected by + ** an AND operator. + */ + if( pRight->pOn ){ + setJoinExpr(pRight->pOn, pRight->iCursor); + p->pWhere = sqlite3ExprAnd(pParse->db, p->pWhere, pRight->pOn); + pRight->pOn = 0; + } + + /* Create extra terms on the WHERE clause for each column named + ** in the USING clause. Example: If the two tables to be joined are + ** A and B and the USING clause names X, Y, and Z, then add this + ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z + ** Report an error if any column mentioned in the USING clause is + ** not contained in both tables to be joined. + */ + if( pRight->pUsing ){ + IdList *pList = pRight->pUsing; + for(j=0; jnId; j++){ + char *zName = pList->a[j].zName; + if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){ + sqlite3ErrorMsg(pParse, "cannot join using column %s - column " + "not present in both tables", zName); + return 1; + } + addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias, + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere); + } + } + } + return 0; +} + +/* +** Insert code into "v" that will push the record on the top of the +** stack into the sorter. +*/ +static void pushOntoSorter( + Parse *pParse, /* Parser context */ + ExprList *pOrderBy, /* The ORDER BY clause */ + Select *pSelect, /* The whole SELECT statement */ + int regData /* Register holding data to be sorted */ +){ + Vdbe *v = pParse->pVdbe; + int nExpr = pOrderBy->nExpr; + int regBase = sqlite3GetTempRange(pParse, nExpr+2); + int regRecord = sqlite3GetTempReg(pParse); + sqlite3ExprCodeExprList(pParse, pOrderBy, regBase); + sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); + sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); + sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); + sqlite3ReleaseTempReg(pParse, regRecord); + sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); + if( pSelect->iLimit>=0 ){ + int addr1, addr2; + int iLimit; + if( pSelect->pOffset ){ + iLimit = pSelect->iOffset+1; + }else{ + iLimit = pSelect->iLimit; + } + addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); + sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); + addr2 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor); + sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor); + sqlite3VdbeJumpHere(v, addr2); + pSelect->iLimit = -1; + } +} + +/* +** Add code to implement the OFFSET +*/ +static void codeOffset( + Vdbe *v, /* Generate code into this VM */ + Select *p, /* The SELECT statement being coded */ + int iContinue /* Jump here to skip the current record */ +){ + if( p->iOffset>=0 && iContinue!=0 ){ + int addr; + sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); + addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset); + sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); + VdbeComment((v, "skip OFFSET records")); + sqlite3VdbeJumpHere(v, addr); + } +} + +/* +** Add code that will check to make sure the N registers starting at iMem +** form a distinct entry. iTab is a sorting index that holds previously +** seen combinations of the N values. A new entry is made in iTab +** if the current N values are new. +** +** A jump to addrRepeat is made and the N+1 values are popped from the +** stack if the top N elements are not distinct. +*/ +static void codeDistinct( + Parse *pParse, /* Parsing and code generating context */ + int iTab, /* A sorting index used to test for distinctness */ + int addrRepeat, /* Jump to here if not distinct */ + int N, /* Number of elements */ + int iMem /* First element */ +){ + Vdbe *v; + int r1; + + v = pParse->pVdbe; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1); + sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1); + sqlite3ReleaseTempReg(pParse, r1); +} + +/* +** Generate an error message when a SELECT is used within a subexpression +** (example: "a IN (SELECT * FROM table)") but it has more than 1 result +** column. We do this in a subroutine because the error occurs in multiple +** places. +*/ +static int checkForMultiColumnSelectError( + Parse *pParse, /* Parse context. */ + SelectDest *pDest, /* Destination of SELECT results */ + int nExpr /* Number of result columns returned by SELECT */ +){ + int eDest = pDest->eDest; + if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ + sqlite3ErrorMsg(pParse, "only a single result allowed for " + "a SELECT that is part of an expression"); + return 1; + }else{ + return 0; + } +} + +/* +** This routine generates the code for the inside of the inner loop +** of a SELECT. +** +** If srcTab and nColumn are both zero, then the pEList expressions +** are evaluated in order to get the data for this row. If nColumn>0 +** then data is pulled from srcTab and pEList is used only to get the +** datatypes for each column. +*/ +static void selectInnerLoop( + Parse *pParse, /* The parser context */ + Select *p, /* The complete select statement being coded */ + ExprList *pEList, /* List of values being extracted */ + int srcTab, /* Pull data from this table */ + int nColumn, /* Number of columns in the source table */ + ExprList *pOrderBy, /* If not NULL, sort results using this key */ + int distinct, /* If >=0, make sure results are distinct */ + SelectDest *pDest, /* How to dispose of the results */ + int iContinue, /* Jump here to continue with next row */ + int iBreak, /* Jump here to break out of the inner loop */ + char *aff /* affinity string if eDest is SRT_Union */ +){ + Vdbe *v = pParse->pVdbe; + int i; + int hasDistinct; /* True if the DISTINCT keyword is present */ + int regResult; /* Start of memory holding result set */ + int eDest = pDest->eDest; /* How to dispose of results */ + int iParm = pDest->iParm; /* First argument to disposal method */ + int nResultCol; /* Number of result columns */ + int nToFree; /* Number of result columns to release */ + + if( v==0 ) return; + assert( pEList!=0 ); + + /* If there was a LIMIT clause on the SELECT statement, then do the check + ** to see if this row should be output. + */ + hasDistinct = distinct>=0 && pEList->nExpr>0; + if( pOrderBy==0 && !hasDistinct ){ + codeOffset(v, p, iContinue); + } + + /* Pull the requested columns. + */ + if( nColumn>0 ){ + nResultCol = nColumn; + }else{ + nResultCol = pEList->nExpr; + } + if( pDest->iMem>0 ){ + regResult = pDest->iMem; + nToFree = 0; + }else{ + pDest->iMem = regResult = sqlite3GetTempRange(pParse, nResultCol); + nToFree = nResultCol; + } + if( nColumn>0 ){ + for(i=0; ia[i].pExpr, regResult+i); + } + } + nColumn = nResultCol; + + /* If the DISTINCT keyword was present on the SELECT statement + ** and this row has been seen before, then do not make this row + ** part of the result. + */ + if( hasDistinct ){ + assert( pEList!=0 ); + assert( pEList->nExpr==nColumn ); + codeDistinct(pParse, distinct, iContinue, nColumn, regResult); + if( pOrderBy==0 ){ + codeOffset(v, p, iContinue); + } + } + + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ + return; + } + + switch( eDest ){ + /* In this mode, write each query result to the key of the temporary + ** table iParm. + */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT + case SRT_Union: { + int r1; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + if( aff ){ + sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); + } + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); + break; + } + + /* Construct a record from the query result, but instead of + ** saving that record, use it as a key to delete elements from + ** the temporary table iParm. + */ + case SRT_Except: { + int r1; + r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); + sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); + break; + } +#endif + + /* Store the result as data using a unique key. + */ + case SRT_Table: + case SRT_EphemTab: { + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + if( pOrderBy ){ + pushOntoSorter(pParse, pOrderBy, p, r1); + }else{ + int r2 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); + sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + sqlite3ReleaseTempReg(pParse, r2); + } + sqlite3ReleaseTempReg(pParse, r1); + break; + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If we are creating a set for an "expr IN (SELECT ...)" construct, + ** then there should be a single item on the stack. Write this + ** item into the set table with bogus data. + */ + case SRT_Set: { + int addr2; + + assert( nColumn==1 ); + addr2 = sqlite3VdbeAddOp1(v, OP_IsNull, regResult); + p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity); + if( pOrderBy ){ + /* At first glance you would think we could optimize out the + ** ORDER BY in this case since the order of entries in the set + ** does not matter. But there might be a LIMIT clause, in which + ** case the order does matter */ + pushOntoSorter(pParse, pOrderBy, p, regResult); + }else{ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); + sqlite3ReleaseTempReg(pParse, r1); + } + sqlite3VdbeJumpHere(v, addr2); + break; + } + + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); + /* The LIMIT clause will terminate the loop for us */ + break; + } + + /* If this is a scalar select that is part of an expression, then + ** store the results in the appropriate memory cell and break out + ** of the scan loop. + */ + case SRT_Mem: { + assert( nColumn==1 ); + if( pOrderBy ){ + pushOntoSorter(pParse, pOrderBy, p, regResult); + }else{ + sqlite3VdbeAddOp2(v, OP_Move, regResult, iParm); + /* The LIMIT clause will jump out of the loop for us */ + } + break; + } +#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ + + /* Send the data to the callback function or to a subroutine. In the + ** case of a subroutine, the subroutine itself is responsible for + ** popping the data from the stack. + */ + case SRT_Subroutine: + case SRT_Callback: { + if( pOrderBy ){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); + pushOntoSorter(pParse, pOrderBy, p, r1); + sqlite3ReleaseTempReg(pParse, r1); + }else if( eDest==SRT_Subroutine ){ + nToFree = 0; /* Preserve registers. Subroutine will need them. */ + sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); + }else{ + sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); + } + break; + } + +#if !defined(SQLITE_OMIT_TRIGGER) + /* Discard the results. This is used for SELECT statements inside + ** the body of a TRIGGER. The purpose of such selects is to call + ** user-defined functions that have side effects. We do not care + ** about the actual results of the select. + */ + default: { + assert( eDest==SRT_Discard ); + break; + } +#endif + } + + /* Jump to the end of the loop if the LIMIT is reached. + */ + if( p->iLimit>=0 && pOrderBy==0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak); + } + sqlite3ReleaseTempRange(pParse, regResult, nToFree); +} + +/* +** Given an expression list, generate a KeyInfo structure that records +** the collating sequence for each expression in that expression list. +** +** If the ExprList is an ORDER BY or GROUP BY clause then the resulting +** KeyInfo structure is appropriate for initializing a virtual index to +** implement that clause. If the ExprList is the result set of a SELECT +** then the KeyInfo structure is appropriate for initializing a virtual +** index to implement a DISTINCT test. +** +** Space to hold the KeyInfo structure is obtain from malloc. The calling +** function is responsible for seeing that this structure is eventually +** freed. Add the KeyInfo structure to the P4 field of an opcode using +** P4_KEYINFO_HANDOFF is the usual way of dealing with this. +*/ +static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ + sqlite3 *db = pParse->db; + int nExpr; + KeyInfo *pInfo; + struct ExprList_item *pItem; + int i; + + nExpr = pList->nExpr; + pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); + if( pInfo ){ + pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr]; + pInfo->nField = nExpr; + pInfo->enc = ENC(db); + for(i=0, pItem=pList->a; ipExpr); + if( !pColl ){ + pColl = db->pDfltColl; + } + pInfo->aColl[i] = pColl; + pInfo->aSortOrder[i] = pItem->sortOrder; + } + } + return pInfo; +} + + +/* +** If the inner loop was generated using a non-null pOrderBy argument, +** then the results were placed in a sorter. After the loop is terminated +** we need to run the sorter and output the results. The following +** routine generates the code needed to do that. +*/ +static void generateSortTail( + Parse *pParse, /* Parsing context */ + Select *p, /* The SELECT statement */ + Vdbe *v, /* Generate code into this VDBE */ + int nColumn, /* Number of columns of data */ + SelectDest *pDest /* Write the sorted results here */ +){ + int brk = sqlite3VdbeMakeLabel(v); + int cont = sqlite3VdbeMakeLabel(v); + int addr; + int iTab; + int pseudoTab = 0; + ExprList *pOrderBy = p->pOrderBy; + + int eDest = pDest->eDest; + int iParm = pDest->iParm; + + int regRow; + int regRowid; + + iTab = pOrderBy->iECursor; + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + pseudoTab = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn); + } + addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); + codeOffset(v, p, cont); + regRow = sqlite3GetTempReg(pParse); + regRowid = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow); + switch( eDest ){ + case SRT_Table: + case SRT_EphemTab: { + sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); + sqlite3VdbeChangeP5(v, OPFLAG_APPEND); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case SRT_Set: { + int j1; + assert( nColumn==1 ); + j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow); + sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRow, &p->affinity, 1); + sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRow); + sqlite3VdbeJumpHere(v, j1); + break; + } + case SRT_Mem: { + assert( nColumn==1 ); + sqlite3VdbeAddOp2(v, OP_Move, regRow, iParm); + /* The LIMIT clause will terminate the loop for us */ + break; + } +#endif + case SRT_Callback: + case SRT_Subroutine: { + int i; + sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); + sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); + for(i=0; iiMem+i); + } + if( eDest==SRT_Callback ){ + sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); + }else{ + sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); + } + break; + } + default: { + /* Do nothing */ + break; + } + } + sqlite3ReleaseTempReg(pParse, regRow); + sqlite3ReleaseTempReg(pParse, regRowid); + + /* Jump to the end of the loop when the LIMIT is reached + */ + if( p->iLimit>=0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, brk); + } + + /* The bottom of the loop + */ + sqlite3VdbeResolveLabel(v, cont); + sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); + sqlite3VdbeResolveLabel(v, brk); + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0); + } + +} + +/* +** Return a pointer to a string containing the 'declaration type' of the +** expression pExpr. The string may be treated as static by the caller. +** +** The declaration type is the exact datatype definition extracted from the +** original CREATE TABLE statement if the expression is a column. The +** declaration type for a ROWID field is INTEGER. Exactly when an expression +** is considered a column can be complex in the presence of subqueries. The +** result-set expression in all of the following SELECT statements is +** considered a column by this function. +** +** SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl); +** SELECT abc FROM (SELECT col AS abc FROM tbl); +** +** The declaration type for any expression other than a column is NULL. +*/ +static const char *columnType( + NameContext *pNC, + Expr *pExpr, + const char **pzOriginDb, + const char **pzOriginTab, + const char **pzOriginCol +){ + char const *zType = 0; + char const *zOriginDb = 0; + char const *zOriginTab = 0; + char const *zOriginCol = 0; + int j; + if( pExpr==0 || pNC->pSrcList==0 ) return 0; + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + /* The expression is a column. Locate the table the column is being + ** extracted from in NameContext.pSrcList. This table may be real + ** database table or a subquery. + */ + Table *pTab = 0; /* Table structure column is extracted from */ + Select *pS = 0; /* Select the column is extracted from */ + int iCol = pExpr->iColumn; /* Index of column in pTab */ + while( pNC && !pTab ){ + SrcList *pTabList = pNC->pSrcList; + for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); + if( jnSrc ){ + pTab = pTabList->a[j].pTab; + pS = pTabList->a[j].pSelect; + }else{ + pNC = pNC->pNext; + } + } + + if( pTab==0 ){ + /* FIX ME: + ** This can occurs if you have something like "SELECT new.x;" inside + ** a trigger. In other words, if you reference the special "new" + ** table in the result set of a select. We do not have a good way + ** to find the actual table type, so call it "TEXT". This is really + ** something of a bug, but I do not know how to fix it. + ** + ** This code does not produce the correct answer - it just prevents + ** a segfault. See ticket #1229. + */ + zType = "TEXT"; + break; + } + + assert( pTab ); + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin + ** data for the result-set column of the sub-select. + */ + 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. + */ + NameContext sNC; + Expr *p = pS->pEList->a[iCol].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = 0; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + } + }else if( pTab->pSchema ){ + /* A real table */ + assert( !pS ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iColnCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + zOriginCol = "rowid"; + }else{ + zType = pTab->aCol[iCol].zType; + zOriginCol = pTab->aCol[iCol].zName; + } + zOriginTab = pTab->zName; + if( pNC->pParse ){ + int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); + zOriginDb = pNC->pParse->db->aDb[iDb].zName; + } + } + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: { + /* The expression is a sub-select. Return the declaration type and + ** origin info for the single column in the result set of the SELECT + ** statement. + */ + NameContext sNC; + Select *pS = pExpr->pSelect; + Expr *p = pS->pEList->a[0].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = pNC; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + break; + } +#endif + } + + if( pzOriginDb ){ + assert( pzOriginTab && pzOriginCol ); + *pzOriginDb = zOriginDb; + *pzOriginTab = zOriginTab; + *pzOriginCol = zOriginCol; + } + return zType; +} + +/* +** Generate code that will tell the VDBE the declaration types of columns +** in the result set. +*/ +static void generateColumnTypes( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* List of tables */ + ExprList *pEList /* Expressions defining the result set */ +){ + Vdbe *v = pParse->pVdbe; + int i; + NameContext sNC; + sNC.pSrcList = pTabList; + sNC.pParse = pParse; + for(i=0; inExpr; i++){ + Expr *p = pEList->a[i].pExpr; + const char *zOrigDb = 0; + const char *zOrigTab = 0; + const char *zOrigCol = 0; + const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + + /* The vdbe must make its own copy of the column-type and other + ** column specific strings, in case the schema is reset before this + ** virtual machine is deleted. + */ + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT); + } +} + +/* +** Generate code that will tell the VDBE the names of columns +** in the result set. This information is used to provide the +** azCol[] values in the callback. +*/ +static void generateColumnNames( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* List of tables */ + ExprList *pEList /* Expressions defining the result set */ +){ + Vdbe *v = pParse->pVdbe; + int i, j; + sqlite3 *db = pParse->db; + int fullNames, shortNames; + +#ifndef SQLITE_OMIT_EXPLAIN + /* If this is an EXPLAIN, skip this step */ + if( pParse->explain ){ + return; + } +#endif + + assert( v!=0 ); + if( pParse->colNamesSet || v==0 || db->mallocFailed ) return; + pParse->colNamesSet = 1; + fullNames = (db->flags & SQLITE_FullColNames)!=0; + shortNames = (db->flags & SQLITE_ShortColNames)!=0; + sqlite3VdbeSetNumCols(v, pEList->nExpr); + for(i=0; inExpr; i++){ + Expr *p; + p = pEList->a[i].pExpr; + if( p==0 ) continue; + if( pEList->a[i].zName ){ + char *zName = pEList->a[i].zName; + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName)); + continue; + } + if( p->op==TK_COLUMN && pTabList ){ + Table *pTab; + char *zCol; + int iCol = p->iColumn; + for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){} + assert( jnSrc ); + pTab = pTabList->a[j].pTab; + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iColnCol) ); + if( iCol<0 ){ + zCol = "rowid"; + }else{ + zCol = pTab->aCol[iCol].zName; + } + if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ + char *zName = 0; + char *zTab; + + zTab = pTabList->a[j].zAlias; + if( fullNames || zTab==0 ) zTab = pTab->zName; + sqlite3SetString(&zName, zTab, ".", zCol, (char*)0); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P4_DYNAMIC); + }else{ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); + } + }else if( p->span.z && p->span.z[0] ){ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + /* sqlite3VdbeCompressSpace(v, addr); */ + }else{ + char zName[30]; + assert( p->op!=TK_COLUMN || pTabList==0 ); + sqlite3_snprintf(sizeof(zName), zName, "column%d", i+1); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0); + } + } + generateColumnTypes(pParse, pTabList, pEList); +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** Name of the connection operator, used for error messages. +*/ +static const char *selectOpName(int id){ + char *z; + switch( id ){ + case TK_ALL: z = "UNION ALL"; break; + case TK_INTERSECT: z = "INTERSECT"; break; + case TK_EXCEPT: z = "EXCEPT"; break; + default: z = "UNION"; break; + } + return z; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +/* +** Forward declaration +*/ +static int prepSelectStmt(Parse*, Select*); + +/* +** Given a SELECT statement, generate a Table structure that describes +** the result set of that SELECT. +*/ +Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ + Table *pTab; + int i, j; + ExprList *pEList; + Column *aCol, *pCol; + sqlite3 *db = pParse->db; + + while( pSelect->pPrior ) pSelect = pSelect->pPrior; + if( prepSelectStmt(pParse, pSelect) ){ + return 0; + } + if( sqlite3SelectResolve(pParse, pSelect, 0) ){ + return 0; + } + pTab = sqlite3DbMallocZero(db, sizeof(Table) ); + if( pTab==0 ){ + return 0; + } + pTab->nRef = 1; + pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0; + pEList = pSelect->pEList; + pTab->nCol = pEList->nExpr; + assert( pTab->nCol>0 ); + pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol); + for(i=0, pCol=aCol; inCol; i++, pCol++){ + Expr *p, *pR; + char *zType; + char *zName; + int nName; + CollSeq *pColl; + int cnt; + NameContext sNC; + + /* Get an appropriate name for the column + */ + p = pEList->a[i].pExpr; + assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); + if( (zName = pEList->a[i].zName)!=0 ){ + /* If the column contains an "AS " phrase, use as the name */ + zName = sqlite3DbStrDup(db, zName); + }else if( p->op==TK_DOT + && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ + /* For columns of the from A.B use B as the name */ + zName = sqlite3MPrintf(db, "%T", &pR->token); + }else if( p->span.z && p->span.z[0] ){ + /* Use the original text of the column expression as its name */ + zName = sqlite3MPrintf(db, "%T", &p->span); + }else{ + /* If all else fails, make up a name */ + zName = sqlite3MPrintf(db, "column%d", i+1); + } + if( !zName || db->mallocFailed ){ + db->mallocFailed = 1; + sqlite3_free(zName); + sqlite3DeleteTable(pTab); + return 0; + } + sqlite3Dequote(zName); + + /* Make sure the column name is unique. If the name is not unique, + ** append a integer to the name so that it becomes unique. + */ + nName = strlen(zName); + for(j=cnt=0; jzName = zName; + + /* Get the typename, type affinity, and collating sequence for the + ** column. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pSrcList = pSelect->pSrc; + zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0)); + pCol->zType = zType; + pCol->affinity = sqlite3ExprAffinity(p); + pColl = sqlite3ExprCollSeq(pParse, p); + if( pColl ){ + pCol->zColl = sqlite3DbStrDup(db, pColl->zName); + } + } + pTab->iPKey = -1; + return pTab; +} + +/* +** Prepare a SELECT statement for processing by doing the following +** things: +** +** (1) Make sure VDBE cursor numbers have been assigned to every +** element of the FROM clause. +** +** (2) Fill in the pTabList->a[].pTab fields in the SrcList that +** defines FROM clause. When views appear in the FROM clause, +** fill pTabList->a[].pSelect with a copy of the SELECT statement +** that implements the view. A copy is made of the view's SELECT +** statement so that we can freely modify or delete that statement +** without worrying about messing up the presistent representation +** of the view. +** +** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword +** on joins and the ON and USING clause of joins. +** +** (4) Scan the list of columns in the result set (pEList) looking +** for instances of the "*" operator or the TABLE.* operator. +** If found, expand each "*" to be every column in every table +** and TABLE.* to be every column in TABLE. +** +** Return 0 on success. If there are problems, leave an error message +** in pParse and return non-zero. +*/ +static int prepSelectStmt(Parse *pParse, Select *p){ + int i, j, k, rc; + SrcList *pTabList; + ExprList *pEList; + struct SrcList_item *pFrom; + sqlite3 *db = pParse->db; + + if( p==0 || p->pSrc==0 || db->mallocFailed ){ + return 1; + } + pTabList = p->pSrc; + pEList = p->pEList; + + /* Make sure cursor numbers have been assigned to all entries in + ** the FROM clause of the SELECT statement. + */ + sqlite3SrcListAssignCursors(pParse, p->pSrc); + + /* Look up every table named in the FROM clause of the select. If + ** an entry of the FROM clause is a subquery instead of a table or view, + ** then create a transient table structure to describe the subquery. + */ + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab; + if( pFrom->pTab!=0 ){ + /* This statement has already been prepared. There is no need + ** to go further. */ + assert( i==0 ); + return 0; + } + if( pFrom->zName==0 ){ +#ifndef SQLITE_OMIT_SUBQUERY + /* A sub-query in the FROM clause of a SELECT */ + assert( pFrom->pSelect!=0 ); + if( pFrom->zAlias==0 ){ + pFrom->zAlias = + sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect); + } + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = + sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); + if( pTab==0 ){ + return 1; + } + /* The isEphem flag indicates that the Table structure has been + ** dynamically allocated and may be freed at any time. In other words, + ** pTab is not pointing to a persistent table structure that defines + ** part of the schema. */ + pTab->isEphem = 1; +#endif + }else{ + /* An ordinary table or view name in the FROM clause */ + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = + sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase); + if( pTab==0 ){ + return 1; + } + pTab->nRef++; +#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) + if( pTab->pSelect || IsVirtual(pTab) ){ + /* We reach here if the named table is a really a view */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + return 1; + } + /* If pFrom->pSelect!=0 it means we are dealing with a + ** view within a view. The SELECT structure has already been + ** copied by the outer view so we can skip the copy step here + ** in the inner view. + */ + if( pFrom->pSelect==0 ){ + pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect); + } + } +#endif + } + } + + /* Process NATURAL keywords, and ON and USING clauses of joins. + */ + if( sqliteProcessJoin(pParse, p) ) return 1; + + /* For every "*" that occurs in the column list, insert the names of + ** all columns in all tables. And for every TABLE.* insert the names + ** of all columns in TABLE. The parser inserted a special expression + ** with the TK_ALL operator for each "*" that it found in the column list. + ** The following code just has to locate the TK_ALL expressions and expand + ** each one to the list of all columns in all tables. + ** + ** The first loop just checks to see if there are any "*" operators + ** that need expanding. + */ + for(k=0; knExpr; k++){ + Expr *pE = pEList->a[k].pExpr; + if( pE->op==TK_ALL ) break; + if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL + && pE->pLeft && pE->pLeft->op==TK_ID ) break; + } + rc = 0; + if( knExpr ){ + /* + ** If we get here it means the result set contains one or more "*" + ** operators that need to be expanded. Loop through each expression + ** in the result set and expand them one by one. + */ + struct ExprList_item *a = pEList->a; + ExprList *pNew = 0; + int flags = pParse->db->flags; + int longNames = (flags & SQLITE_FullColNames)!=0 && + (flags & SQLITE_ShortColNames)==0; + + for(k=0; knExpr; k++){ + Expr *pE = a[k].pExpr; + if( pE->op!=TK_ALL && + (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){ + /* This particular expression does not need to be expanded. + */ + pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0); + if( pNew ){ + pNew->a[pNew->nExpr-1].zName = a[k].zName; + }else{ + rc = 1; + } + a[k].pExpr = 0; + a[k].zName = 0; + }else{ + /* This expression is a "*" or a "TABLE.*" and needs to be + ** expanded. */ + int tableSeen = 0; /* Set to 1 when TABLE matches */ + char *zTName; /* text of name of TABLE */ + if( pE->op==TK_DOT && pE->pLeft ){ + zTName = sqlite3NameFromToken(db, &pE->pLeft->token); + }else{ + zTName = 0; + } + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + char *zTabName = pFrom->zAlias; + if( zTabName==0 || zTabName[0]==0 ){ + zTabName = pTab->zName; + } + if( zTName && (zTabName==0 || zTabName[0]==0 || + sqlite3StrICmp(zTName, zTabName)!=0) ){ + continue; + } + tableSeen = 1; + for(j=0; jnCol; j++){ + Expr *pExpr, *pRight; + char *zName = pTab->aCol[j].zName; + + /* If a column is marked as 'hidden' (currently only possible + ** for virtual tables), do not include it in the expanded + ** result-set list. + */ + if( IsHiddenColumn(&pTab->aCol[j]) ){ + assert(IsVirtual(pTab)); + continue; + } + + if( i>0 ){ + struct SrcList_item *pLeft = &pTabList->a[i-1]; + if( (pLeft[1].jointype & JT_NATURAL)!=0 && + columnIndex(pLeft->pTab, zName)>=0 ){ + /* In a NATURAL join, omit the join columns from the + ** table on the right */ + continue; + } + if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){ + /* In a join with a USING clause, omit columns in the + ** using clause from the table on the right. */ + continue; + } + } + pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); + if( pRight==0 ) break; + setQuotedToken(pParse, &pRight->token, zName); + if( zTabName && (longNames || pTabList->nSrc>1) ){ + Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0); + pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); + if( pExpr==0 ) break; + setQuotedToken(pParse, &pLeft->token, zTabName); + setToken(&pExpr->span, + sqlite3MPrintf(db, "%s.%s", zTabName, zName)); + pExpr->span.dyn = 1; + pExpr->token.z = 0; + pExpr->token.n = 0; + pExpr->token.dyn = 0; + }else{ + pExpr = pRight; + pExpr->span = pExpr->token; + pExpr->span.dyn = 0; + } + if( longNames ){ + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span); + }else{ + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token); + } + } + } + if( !tableSeen ){ + if( zTName ){ + sqlite3ErrorMsg(pParse, "no such table: %s", zTName); + }else{ + sqlite3ErrorMsg(pParse, "no tables specified"); + } + rc = 1; + } + sqlite3_free(zTName); + } + } + sqlite3ExprListDelete(pEList); + p->pEList = pNew; + } + if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){ + sqlite3ErrorMsg(pParse, "too many columns in result set"); + rc = SQLITE_ERROR; + } + if( db->mallocFailed ){ + rc = SQLITE_NOMEM; + } + return rc; +} + +/* +** pE is a pointer to an expression which is a single term in +** ORDER BY or GROUP BY clause. +** +** If pE evaluates to an integer constant i, then return i. +** This is an indication to the caller that it should sort +** by the i-th column of the result set. +** +** If pE is a well-formed expression and the SELECT statement +** is not compound, then return 0. This indicates to the +** caller that it should sort by the value of the ORDER BY +** expression. +** +** If the SELECT is compound, then attempt to match pE against +** result set columns in the left-most SELECT statement. Return +** the index i of the matching column, as an indication to the +** caller that it should sort by the i-th column. If there is +** no match, return -1 and leave an error message in pParse. +*/ +static int matchOrderByTermToExprList( + Parse *pParse, /* Parsing context for error messages */ + Select *pSelect, /* The SELECT statement with the ORDER BY clause */ + Expr *pE, /* The specific ORDER BY term */ + int idx, /* When ORDER BY term is this */ + int isCompound, /* True if this is a compound SELECT */ + u8 *pHasAgg /* True if expression contains aggregate functions */ +){ + int i; /* Loop counter */ + ExprList *pEList; /* The columns of the result set */ + NameContext nc; /* Name context for resolving pE */ + + + /* If the term is an integer constant, return the value of that + ** constant */ + pEList = pSelect->pEList; + if( sqlite3ExprIsInteger(pE, &i) ){ + if( i<=0 ){ + /* If i is too small, make it too big. That way the calling + ** function still sees a value that is out of range, but does + ** not confuse the column number with 0 or -1 result code. + */ + i = pEList->nExpr+1; + } + return i; + } + + /* If the term is a simple identifier that try to match that identifier + ** against a column name in the result set. + */ + if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){ + sqlite3 *db = pParse->db; + char *zCol = sqlite3NameFromToken(db, &pE->token); + if( zCol==0 ){ + return -1; + } + for(i=0; inExpr; i++){ + char *zAs = pEList->a[i].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + sqlite3_free(zCol); + return i+1; + } + } + sqlite3_free(zCol); + } + + /* Resolve all names in the ORDER BY term expression + */ + memset(&nc, 0, sizeof(nc)); + nc.pParse = pParse; + nc.pSrcList = pSelect->pSrc; + nc.pEList = pEList; + nc.allowAgg = 1; + nc.nErr = 0; + if( sqlite3ExprResolveNames(&nc, pE) ){ + if( isCompound ){ + sqlite3ErrorClear(pParse); + return 0; + }else{ + return -1; + } + } + if( nc.hasAgg && pHasAgg ){ + *pHasAgg = 1; + } + + /* For a compound SELECT, we need to try to match the ORDER BY + ** expression against an expression in the result set + */ + if( isCompound ){ + for(i=0; inExpr; i++){ + if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){ + return i+1; + } + } + } + return 0; +} + + +/* +** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement. +** Return the number of errors seen. +** +** Every term of the ORDER BY or GROUP BY clause needs to be an +** expression. If any expression is an integer constant, then +** that expression is replaced by the corresponding +** expression from the result set. +*/ +static int processOrderGroupBy( + Parse *pParse, /* Parsing context. Leave error messages here */ + Select *pSelect, /* The SELECT statement containing the clause */ + ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ + int isOrder, /* 1 for ORDER BY. 0 for GROUP BY */ + u8 *pHasAgg /* Set to TRUE if any term contains an aggregate */ +){ + int i; + sqlite3 *db = pParse->db; + ExprList *pEList; + + if( pOrderBy==0 || pParse->db->mallocFailed ) return 0; + if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){ + const char *zType = isOrder ? "ORDER" : "GROUP"; + sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); + return 1; + } + pEList = pSelect->pEList; + if( pEList==0 ){ + return 0; + } + for(i=0; inExpr; i++){ + int iCol; + Expr *pE = pOrderBy->a[i].pExpr; + iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg); + if( iCol<0 ){ + return 1; + } + if( iCol>pEList->nExpr ){ + const char *zType = isOrder ? "ORDER" : "GROUP"; + sqlite3ErrorMsg(pParse, + "%r %s BY term out of range - should be " + "between 1 and %d", i+1, zType, pEList->nExpr); + return 1; + } + if( iCol>0 ){ + CollSeq *pColl = pE->pColl; + int flags = pE->flags & EP_ExpCollate; + sqlite3ExprDelete(pE); + pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr); + pOrderBy->a[i].pExpr = pE; + if( pE && pColl && flags ){ + pE->pColl = pColl; + pE->flags |= flags; + } + } + } + return 0; +} + +/* +** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return +** the number of errors seen. +** +** The processing depends on whether the SELECT is simple or compound. +** For a simple SELECT statement, evry term of the ORDER BY or GROUP BY +** clause needs to be an expression. If any expression is an integer +** constant, then that expression is replaced by the corresponding +** expression from the result set. +** +** For compound SELECT statements, every expression needs to be of +** type TK_COLUMN with a iTable value as given in the 4th parameter. +** If any expression is an integer, that becomes the column number. +** Otherwise, match the expression against result set columns from +** the left-most SELECT. +*/ +static int processCompoundOrderBy( + Parse *pParse, /* Parsing context. Leave error messages here */ + Select *pSelect, /* The SELECT statement containing the ORDER BY */ + int iTable /* Output table for compound SELECT statements */ +){ + int i; + ExprList *pOrderBy; + ExprList *pEList; + sqlite3 *db; + int moreToDo = 1; + + pOrderBy = pSelect->pOrderBy; + if( pOrderBy==0 ) return 0; + if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){ + sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); + return 1; + } + db = pParse->db; + for(i=0; inExpr; i++){ + pOrderBy->a[i].done = 0; + } + while( pSelect->pPrior ){ + pSelect = pSelect->pPrior; + } + while( pSelect && moreToDo ){ + moreToDo = 0; + for(i=0; inExpr; i++){ + int iCol = -1; + Expr *pE, *pDup; + if( pOrderBy->a[i].done ) continue; + pE = pOrderBy->a[i].pExpr; + pDup = sqlite3ExprDup(db, pE); + if( !db->mallocFailed ){ + assert(pDup); + iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0); + } + sqlite3ExprDelete(pDup); + if( iCol<0 ){ + return 1; + } + pEList = pSelect->pEList; + if( pEList==0 ){ + return 1; + } + if( iCol>pEList->nExpr ){ + sqlite3ErrorMsg(pParse, + "%r ORDER BY term out of range - should be " + "between 1 and %d", i+1, pEList->nExpr); + return 1; + } + if( iCol>0 ){ + pE->op = TK_COLUMN; + pE->iTable = iTable; + pE->iAgg = -1; + pE->iColumn = iCol-1; + pE->pTab = 0; + pOrderBy->a[i].done = 1; + }else{ + moreToDo = 1; + } + } + pSelect = pSelect->pNext; + } + for(i=0; inExpr; i++){ + if( pOrderBy->a[i].done==0 ){ + sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " + "column in the result set", i+1); + return 1; + } + } + return 0; +} + +/* +** Get a VDBE for the given parser context. Create a new one if necessary. +** If an error occurs, return NULL and leave a message in pParse. +*/ +Vdbe *sqlite3GetVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe; + if( v==0 ){ + v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); +#ifndef SQLITE_OMIT_TRACE + if( v ){ + sqlite3VdbeAddOp0(v, OP_Trace); + } +#endif + } + return v; +} + + +/* +** Compute the iLimit and iOffset fields of the SELECT based on the +** pLimit and pOffset expressions. pLimit and pOffset hold the expressions +** that appear in the original SQL statement after the LIMIT and OFFSET +** keywords. Or NULL if those keywords are omitted. iLimit and iOffset +** are the integer memory register numbers for counters used to compute +** the limit and offset. If there is no limit and/or offset, then +** iLimit and iOffset are negative. +** +** This routine changes the values of iLimit and iOffset only if +** a limit or offset is defined by pLimit and pOffset. iLimit and +** iOffset should have been preset to appropriate default values +** (usually but not always -1) prior to calling this routine. +** Only if pLimit!=0 or pOffset!=0 do the limit registers get +** redefined. The UNION ALL operator uses this property to force +** the reuse of the same limit and offset registers across multiple +** SELECT statements. +*/ +static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ + Vdbe *v = 0; + int iLimit = 0; + int iOffset; + int addr1; + + /* + ** "LIMIT -1" always shows all rows. There is some + ** contraversy about what the correct behavior should be. + ** The current implementation interprets "LIMIT 0" to mean + ** no rows. + */ + if( p->pLimit ){ + p->iLimit = iLimit = ++pParse->nMem; + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3ExprCode(pParse, p->pLimit, iLimit); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); + VdbeComment((v, "LIMIT counter")); + sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); + } + if( p->pOffset ){ + p->iOffset = iOffset = ++pParse->nMem; + if( p->pLimit ){ + pParse->nMem++; /* Allocate an extra register for limit+offset */ + } + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3ExprCode(pParse, p->pOffset, iOffset); + sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); + VdbeComment((v, "OFFSET counter")); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); + sqlite3VdbeJumpHere(v, addr1); + if( p->pLimit ){ + sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); + VdbeComment((v, "LIMIT+OFFSET")); + addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); + sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); + sqlite3VdbeJumpHere(v, addr1); + } + } +} + +/* +** Allocate a virtual index to use for sorting. +*/ +static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){ + if( pOrderBy ){ + int addr; + assert( pOrderBy->iECursor==0 ); + pOrderBy->iECursor = pParse->nTab++; + addr = sqlite3VdbeAddOp2(pParse->pVdbe, OP_OpenEphemeral, + pOrderBy->iECursor, pOrderBy->nExpr+1); + assert( p->addrOpenEphm[2] == -1 ); + p->addrOpenEphm[2] = addr; + } +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** Return the appropriate collating sequence for the iCol-th column of +** the result set for the compound-select statement "p". Return NULL if +** the column has no default collating sequence. +** +** The collating sequence for the compound select is taken from the +** left-most term of the select that has a collating sequence. +*/ +static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ + CollSeq *pRet; + if( p->pPrior ){ + pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); + }else{ + pRet = 0; + } + if( pRet==0 ){ + pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); + } + return pRet; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** This routine is called to process a query that is really the union +** or intersection of two or more separate queries. +** +** "p" points to the right-most of the two queries. the query on the +** left is p->pPrior. The left query could also be a compound query +** in which case this routine will be called recursively. +** +** The results of the total query are to be written into a destination +** of type eDest with parameter iParm. +** +** Example 1: Consider a three-way compound SQL statement. +** +** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 +** +** This statement is parsed up as follows: +** +** SELECT c FROM t3 +** | +** `-----> SELECT b FROM t2 +** | +** `------> SELECT a FROM t1 +** +** The arrows in the diagram above represent the Select.pPrior pointer. +** So if this routine is called with p equal to the t3 query, then +** pPrior will be the t2 query. p->op will be TK_UNION in this case. +** +** Notice that because of the way SQLite parses compound SELECTs, the +** individual selects always group from left to right. +*/ +static int multiSelect( + Parse *pParse, /* Parsing context */ + Select *p, /* The right-most of SELECTs to be coded */ + SelectDest *pDest, /* What to do with query results */ + char *aff /* If eDest is SRT_Union, the affinity string */ +){ + int rc = SQLITE_OK; /* Success code from a subroutine */ + Select *pPrior; /* Another SELECT immediately to our left */ + Vdbe *v; /* Generate code to this VDBE */ + int nCol; /* Number of columns in the result set */ + ExprList *pOrderBy; /* The ORDER BY clause on p */ + int aSetP2[2]; /* Set P2 value of these op to number of columns */ + int nSetP2 = 0; /* Number of slots in aSetP2[] used */ + SelectDest dest; /* Alternative data destination */ + + dest = *pDest; + + /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only + ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. + */ + if( p==0 || p->pPrior==0 ){ + rc = 1; + goto multi_select_end; + } + pPrior = p->pPrior; + assert( pPrior->pRightmost!=pPrior ); + assert( pPrior->pRightmost==p->pRightmost ); + if( pPrior->pOrderBy ){ + sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + if( pPrior->pLimit ){ + sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + + /* Make sure we have a valid query engine. If not, create a new one. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + rc = 1; + goto multi_select_end; + } + + /* Create the destination temporary table if necessary + */ + if( dest.eDest==SRT_EphemTab ){ + assert( p->pEList ); + assert( nSetP2pOrderBy; + switch( p->op ){ + case TK_ALL: { + if( pOrderBy==0 ){ + int addr = 0; + assert( !pPrior->pLimit ); + pPrior->pLimit = p->pLimit; + pPrior->pOffset = p->pOffset; + rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0, aff); + p->pLimit = 0; + p->pOffset = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit>=0 ){ + addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); + VdbeComment((v, "Jump ahead if LIMIT reached")); + } + rc = sqlite3Select(pParse, p, &dest, 0, 0, 0, aff); + p->pPrior = pPrior; + if( rc ){ + goto multi_select_end; + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + /* For UNION ALL ... ORDER BY fall through to the next case */ + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temporary table holding result */ + int op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ + int addr; + SelectDest uniondest; + + priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; + if( dest.eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + unionTab = dest.iParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + if( processCompoundOrderBy(pParse, p, unionTab) ){ + rc = 1; + goto multi_select_end; + } + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); + if( priorOp==SRT_Table ){ + assert( nSetP2addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; + } + createSortingIndex(pParse, p, pOrderBy); + assert( p->pEList ); + } + + /* Code the SELECT statements to our left + */ + assert( !pPrior->pOrderBy ); + sqlite3SelectDestInit(&uniondest, priorOp, unionTab); + rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0, aff); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement + */ + switch( p->op ){ + case TK_EXCEPT: op = SRT_Except; break; + case TK_UNION: op = SRT_Union; break; + case TK_ALL: op = SRT_Table; break; + } + p->pPrior = 0; + p->pOrderBy = 0; + p->disallowOrderBy = pOrderBy!=0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + uniondest.eDest = op; + rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0, aff); + /* Query flattening in sqlite3Select() might refill p->pOrderBy. + ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ + sqlite3ExprListDelete(p->pOrderBy); + p->pPrior = pPrior; + p->pOrderBy = pOrderBy; + sqlite3ExprDelete(p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + p->iLimit = -1; + p->iOffset = -1; + if( rc ){ + goto multi_select_end; + } + + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + if( dest.eDest!=priorOp || unionTab!=dest.iParm ){ + int iCont, iBreak, iStart; + assert( p->pEList ); + if( dest.eDest==SRT_Callback ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); + iStart = sqlite3VdbeCurrentAddr(v); + selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, + pOrderBy, -1, &dest, iCont, iBreak, 0); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); + } + break; + } + case TK_INTERSECT: { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit, *pOffset; + int addr; + SelectDest intersectdest; + int r1; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; + if( processCompoundOrderBy(pParse, p, tab1) ){ + rc = 1; + goto multi_select_end; + } + createSortingIndex(pParse, p, pOrderBy); + + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; + assert( p->pEList ); + + /* Code the SELECTs to our left into temporary table "tab1". + */ + sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1); + rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0, aff); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + intersectdest.iParm = tab2; + rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0, aff); + p->pPrior = pPrior; + sqlite3ExprDelete(p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + if( rc ){ + goto multi_select_end; + } + + /* Generate code to take the intersection of the two temporary + ** tables. + */ + assert( p->pEList ); + if( dest.eDest==SRT_Callback ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); + r1 = sqlite3GetTempReg(pParse); + iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); + sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1); + sqlite3ReleaseTempReg(pParse, r1); + selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, + pOrderBy, -1, &dest, iCont, iBreak, 0); + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); + sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); + break; + } + } + + /* Make sure all SELECTs in the statement have the same number of elements + ** in their result sets. + */ + assert( p->pEList && pPrior->pEList ); + if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ + sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" + " do not have the same number of result columns", selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + + /* Set the number of columns in temporary tables + */ + nCol = p->pEList->nExpr; + while( nSetP2 ){ + sqlite3VdbeChangeP2(v, aSetP2[--nSetP2], nCol); + } + + /* Compute collating sequences used by either the ORDER BY clause or + ** by any temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. Invoke the + ** ORDER BY processing if there is an ORDER BY clause. + ** + ** This section is run by the right-most SELECT statement only. + ** SELECT statements to the left always skip this part. The right-most + ** SELECT might also skip this part if it has no ORDER BY clause and + ** no temp tables are required. + */ + if( pOrderBy || p->usesEphm ){ + int i; /* Loop counter */ + KeyInfo *pKeyInfo; /* Collating sequence for the result set */ + Select *pLoop; /* For looping through SELECT statements */ + int nKeyCol; /* Number of entries in pKeyInfo->aCol[] */ + CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ + CollSeq **aCopy; /* A copy of pKeyInfo->aColl[] */ + + assert( p->pRightmost==p ); + nKeyCol = nCol + (pOrderBy ? pOrderBy->nExpr : 0); + pKeyInfo = sqlite3DbMallocZero(pParse->db, + sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1)); + if( !pKeyInfo ){ + rc = SQLITE_NOMEM; + goto multi_select_end; + } + + pKeyInfo->enc = ENC(pParse->db); + pKeyInfo->nField = nCol; + + for(i=0, apColl=pKeyInfo->aColl; idb->pDfltColl; + } + } + + for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ + for(i=0; i<2; i++){ + int addr = pLoop->addrOpenEphm[i]; + if( addr<0 ){ + /* If [0] is unused then [1] is also unused. So we can + ** always safely abort as soon as the first unused slot is found */ + assert( pLoop->addrOpenEphm[1]<0 ); + break; + } + sqlite3VdbeChangeP2(v, addr, nCol); + sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO); + pLoop->addrOpenEphm[i] = -1; + } + } + + if( pOrderBy ){ + struct ExprList_item *pOTerm = pOrderBy->a; + int nOrderByExpr = pOrderBy->nExpr; + int addr; + u8 *pSortOrder; + + /* Reuse the same pKeyInfo for the ORDER BY as was used above for + ** the compound select statements. Except we have to change out the + ** pKeyInfo->aColl[] values. Some of the aColl[] values will be + ** reused when constructing the pKeyInfo for the ORDER BY, so make + ** a copy. Sufficient space to hold both the nCol entries for + ** the compound select and the nOrderbyExpr entries for the ORDER BY + ** was allocated above. But we need to move the compound select + ** entries out of the way before constructing the ORDER BY entries. + ** Move the compound select entries into aCopy[] where they can be + ** accessed and reused when constructing the ORDER BY entries. + ** Because nCol might be greater than or less than nOrderByExpr + ** we have to use memmove() when doing the copy. + */ + aCopy = &pKeyInfo->aColl[nOrderByExpr]; + pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol]; + memmove(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*)); + + apColl = pKeyInfo->aColl; + for(i=0; ipExpr; + if( (pExpr->flags & EP_ExpCollate) ){ + assert( pExpr->pColl!=0 ); + *apColl = pExpr->pColl; + }else{ + *apColl = aCopy[pExpr->iColumn]; + } + *pSortOrder = pOTerm->sortOrder; + } + assert( p->pRightmost==p ); + assert( p->addrOpenEphm[2]>=0 ); + addr = p->addrOpenEphm[2]; + sqlite3VdbeChangeP2(v, addr, p->pOrderBy->nExpr+2); + pKeyInfo->nField = nOrderByExpr; + sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + pKeyInfo = 0; + generateSortTail(pParse, p, v, p->pEList->nExpr, &dest); + } + + sqlite3_free(pKeyInfo); + } + +multi_select_end: + pDest->iMem = dest.iMem; + return rc; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +#ifndef SQLITE_OMIT_VIEW +/* Forward Declarations */ +static void substExprList(sqlite3*, ExprList*, int, ExprList*); +static void substSelect(sqlite3*, Select *, int, ExprList *); + +/* +** Scan through the expression pExpr. Replace every reference to +** a column in table number iTable with a copy of the iColumn-th +** entry in pEList. (But leave references to the ROWID column +** unchanged.) +** +** This routine is part of the flattening procedure. A subquery +** whose result set is defined by pEList appears as entry in the +** FROM clause of a SELECT such that the VDBE cursor assigned to that +** FORM clause entry is iTable. This routine make the necessary +** changes to pExpr so that it refers directly to the source table +** of the subquery rather the result set of the subquery. +*/ +static void substExpr( + sqlite3 *db, /* Report malloc errors to this connection */ + Expr *pExpr, /* Expr in which substitution occurs */ + int iTable, /* Table to be substituted */ + ExprList *pEList /* Substitute expressions */ +){ + if( pExpr==0 ) return; + if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ + if( pExpr->iColumn<0 ){ + pExpr->op = TK_NULL; + }else{ + Expr *pNew; + assert( pEList!=0 && pExpr->iColumnnExpr ); + assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 ); + pNew = pEList->a[pExpr->iColumn].pExpr; + assert( pNew!=0 ); + pExpr->op = pNew->op; + assert( pExpr->pLeft==0 ); + pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft); + assert( pExpr->pRight==0 ); + pExpr->pRight = sqlite3ExprDup(db, pNew->pRight); + assert( pExpr->pList==0 ); + pExpr->pList = sqlite3ExprListDup(db, pNew->pList); + pExpr->iTable = pNew->iTable; + pExpr->pTab = pNew->pTab; + pExpr->iColumn = pNew->iColumn; + pExpr->iAgg = pNew->iAgg; + sqlite3TokenCopy(db, &pExpr->token, &pNew->token); + sqlite3TokenCopy(db, &pExpr->span, &pNew->span); + pExpr->pSelect = sqlite3SelectDup(db, pNew->pSelect); + pExpr->flags = pNew->flags; + } + }else{ + substExpr(db, pExpr->pLeft, iTable, pEList); + substExpr(db, pExpr->pRight, iTable, pEList); + substSelect(db, pExpr->pSelect, iTable, pEList); + substExprList(db, pExpr->pList, iTable, pEList); + } +} +static void substExprList( + sqlite3 *db, /* Report malloc errors here */ + ExprList *pList, /* List to scan and in which to make substitutes */ + int iTable, /* Table to be substituted */ + ExprList *pEList /* Substitute values */ +){ + int i; + if( pList==0 ) return; + for(i=0; inExpr; i++){ + substExpr(db, pList->a[i].pExpr, iTable, pEList); + } +} +static void substSelect( + sqlite3 *db, /* Report malloc errors here */ + Select *p, /* SELECT statement in which to make substitutions */ + int iTable, /* Table to be replaced */ + ExprList *pEList /* Substitute values */ +){ + if( !p ) return; + substExprList(db, p->pEList, iTable, pEList); + substExprList(db, p->pGroupBy, iTable, pEList); + substExprList(db, p->pOrderBy, iTable, pEList); + substExpr(db, p->pHaving, iTable, pEList); + substExpr(db, p->pWhere, iTable, pEList); + substSelect(db, p->pPrior, iTable, pEList); +} +#endif /* !defined(SQLITE_OMIT_VIEW) */ + +#ifndef SQLITE_OMIT_VIEW +/* +** This routine attempts to flatten subqueries in order to speed +** execution. It returns 1 if it makes changes and 0 if no flattening +** occurs. +** +** To understand the concept of flattening, consider the following +** query: +** +** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 +** +** The default way of implementing this query is to execute the +** subquery first and store the results in a temporary table, then +** run the outer query on that temporary table. This requires two +** passes over the data. Furthermore, because the temporary table +** has no indices, the WHERE clause on the outer query cannot be +** optimized. +** +** This routine attempts to rewrite queries such as the above into +** a single flat select, like this: +** +** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 +** +** The code generated for this simpification gives the same result +** but only has to scan the data once. And because indices might +** exist on the table t1, a complete scan of the data might be +** avoided. +** +** Flattening is only attempted if all of the following are true: +** +** (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. +** +** (3) The subquery is not the right operand of a left outer join, or +** the subquery is not itself a join. (Ticket #306) +** +** (4) The subquery is not DISTINCT or the outer query is not a join. +** +** (5) The subquery is not DISTINCT or the outer query does not use +** aggregates. +** +** (6) The subquery does not use aggregates or the outer query is not +** DISTINCT. +** +** (7) The subquery has a FROM clause. +** +** (8) The subquery does not use LIMIT or the outer query is not a join. +** +** (9) The subquery does not use LIMIT or the outer query does not use +** aggregates. +** +** (10) The subquery does not use aggregates or the outer query does not +** use LIMIT. +** +** (11) The subquery and the outer query do not both have ORDER BY clauses. +** +** (12) The subquery is not the right term of a LEFT OUTER JOIN or the +** subquery has no WHERE clause. (added by ticket #350) +** +** (13) The subquery and outer query do not both use LIMIT +** +** (14) The subquery does not use OFFSET +** +** (15) The outer query is not part of a compound select or the +** subquery does not have both an ORDER BY and a LIMIT clause. +** (See ticket #2339) +** +** In this routine, the "p" parameter is a pointer to the outer query. +** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query +** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. +** +** If flattening is not attempted, this routine is a no-op and returns 0. +** If flattening is attempted this routine returns 1. +** +** All of the expression analysis must occur on both the outer query and +** the subquery before this routine runs. +*/ +static int flattenSubquery( + sqlite3 *db, /* Database connection */ + Select *p, /* The parent or outer SELECT statement */ + int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ + int isAgg, /* True if outer SELECT uses aggregate functions */ + int subqueryIsAgg /* True if the subquery uses aggregate functions */ +){ + Select *pSub; /* The inner query or "subquery" */ + SrcList *pSrc; /* The FROM clause of the outer query */ + SrcList *pSubSrc; /* The FROM clause of the subquery */ + ExprList *pList; /* The result set of the outer query */ + int iParent; /* VDBE cursor number of the pSub result set temp table */ + int i; /* Loop counter */ + Expr *pWhere; /* The WHERE clause */ + struct SrcList_item *pSubitem; /* The subquery */ + + /* Check to see if flattening is permitted. Return 0 if not. + */ + if( p==0 ) return 0; + pSrc = p->pSrc; + assert( pSrc && iFrom>=0 && iFromnSrc ); + pSubitem = &pSrc->a[iFrom]; + pSub = pSubitem->pSelect; + assert( pSub!=0 ); + if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ + pSubSrc = pSub->pSrc; + assert( pSubSrc ); + /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, + ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET + ** because they could be computed at compile-time. But when LIMIT and OFFSET + ** became arbitrary expressions, we were forced to add restrictions (13) + ** and (14). */ + if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ + if( pSub->pOffset ) return 0; /* Restriction (14) */ + if( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){ + return 0; /* Restriction (15) */ + } + if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ + if( (pSub->isDistinct || pSub->pLimit) + && (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */ + return 0; + } + if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */ + if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){ + return 0; /* Restriction (11) */ + } + + /* Restriction 3: If the subquery is a join, make sure the subquery is + ** not used as the right operand of an outer join. Examples of why this + ** is not allowed: + ** + ** t1 LEFT OUTER JOIN (t2 JOIN t3) + ** + ** If we flatten the above, we would get + ** + ** (t1 LEFT OUTER JOIN t2) JOIN t3 + ** + ** which is not at all the same thing. + */ + if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){ + return 0; + } + + /* Restriction 12: If the subquery is the right operand of a left outer + ** join, make sure the subquery has no WHERE clause. + ** An examples of why this is not allowed: + ** + ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) + ** + ** If we flatten the above, we would get + ** + ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 + ** + ** But the t2.x>0 test will always fail on a NULL row of t2, which + ** effectively converts the OUTER JOIN into an INNER JOIN. + */ + if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){ + return 0; + } + + /* If we reach this point, it means flattening is permitted for the + ** iFrom-th entry of the FROM clause in the outer query. + */ + + /* Move all of the FROM elements of the subquery into the + ** the FROM clause of the outer query. Before doing this, remember + ** the cursor number for the original outer query FROM element in + ** iParent. The iParent cursor will never be used. Subsequent code + ** will scan expressions looking for iParent references and replace + ** those references with expressions that resolve to the subquery FROM + ** elements we are now copying in. + */ + iParent = pSubitem->iCursor; + { + int nSubSrc = pSubSrc->nSrc; + int jointype = pSubitem->jointype; + + sqlite3DeleteTable(pSubitem->pTab); + sqlite3_free(pSubitem->zDatabase); + sqlite3_free(pSubitem->zName); + sqlite3_free(pSubitem->zAlias); + pSubitem->pTab = 0; + pSubitem->zDatabase = 0; + pSubitem->zName = 0; + pSubitem->zAlias = 0; + if( nSubSrc>1 ){ + int extra = nSubSrc - 1; + for(i=1; ipSrc = 0; + return 1; + } + } + p->pSrc = pSrc; + for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ + pSrc->a[i] = pSrc->a[i-extra]; + } + } + for(i=0; ia[i+iFrom] = pSubSrc->a[i]; + memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); + } + pSrc->a[iFrom].jointype = jointype; + } + + /* Now begin substituting subquery result set expressions for + ** references to the iParent in the outer query. + ** + ** Example: + ** + ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; + ** \ \_____________ subquery __________/ / + ** \_____________________ outer query ______________________________/ + ** + ** We look at every expression in the outer query and every place we see + ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". + */ + pList = p->pEList; + for(i=0; inExpr; i++){ + Expr *pExpr; + if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ + pList->a[i].zName = + sqlite3DbStrNDup(db, (char*)pExpr->span.z, pExpr->span.n); + } + } + substExprList(db, p->pEList, iParent, pSub->pEList); + if( isAgg ){ + substExprList(db, p->pGroupBy, iParent, pSub->pEList); + substExpr(db, p->pHaving, iParent, pSub->pEList); + } + if( pSub->pOrderBy ){ + assert( p->pOrderBy==0 ); + p->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + }else if( p->pOrderBy ){ + substExprList(db, p->pOrderBy, iParent, pSub->pEList); + } + if( pSub->pWhere ){ + pWhere = sqlite3ExprDup(db, pSub->pWhere); + }else{ + pWhere = 0; + } + if( subqueryIsAgg ){ + assert( p->pHaving==0 ); + p->pHaving = p->pWhere; + p->pWhere = pWhere; + substExpr(db, p->pHaving, iParent, pSub->pEList); + p->pHaving = sqlite3ExprAnd(db, p->pHaving, + sqlite3ExprDup(db, pSub->pHaving)); + assert( p->pGroupBy==0 ); + p->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy); + }else{ + substExpr(db, p->pWhere, iParent, pSub->pEList); + p->pWhere = sqlite3ExprAnd(db, p->pWhere, pWhere); + } + + /* The flattened query is distinct if either the inner or the + ** outer query is distinct. + */ + p->isDistinct = p->isDistinct || pSub->isDistinct; + + /* + ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; + ** + ** One is tempted to try to add a and b to combine the limits. But this + ** does not work if either limit is negative. + */ + if( pSub->pLimit ){ + p->pLimit = pSub->pLimit; + pSub->pLimit = 0; + } + + /* Finially, delete what is left of the subquery and return + ** success. + */ + sqlite3SelectDelete(pSub); + return 1; +} +#endif /* SQLITE_OMIT_VIEW */ + +/* +** Analyze the SELECT statement passed as an argument to see if it +** is a min() or max() query. Return ORDERBY_MIN or ORDERBY_MAX if +** it is, or 0 otherwise. At present, a query is considered to be +** a min()/max() query if: +** +** 1. There is a single object in the FROM clause. +** +** 2. There is a single expression in the result set, and it is +** either min(x) or max(x), where x is a column reference. +*/ +static int minMaxQuery(Parse *pParse, Select *p){ + Expr *pExpr; + ExprList *pEList = p->pEList; + + if( pEList->nExpr!=1 ) return ORDERBY_NORMAL; + pExpr = pEList->a[0].pExpr; + pEList = pExpr->pList; + if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0; + if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return ORDERBY_NORMAL; + if( pExpr->token.n!=3 ) return ORDERBY_NORMAL; + if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ + return ORDERBY_MIN; + }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ + return ORDERBY_MAX; + } + return ORDERBY_NORMAL; +} + +/* +** This routine resolves any names used in the result set of the +** supplied SELECT statement. If the SELECT statement being resolved +** is a sub-select, then pOuterNC is a pointer to the NameContext +** of the parent SELECT. +*/ +int sqlite3SelectResolve( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + NameContext *pOuterNC /* The outer name context. May be NULL. */ +){ + ExprList *pEList; /* Result set. */ + int i; /* For-loop variable used in multiple places */ + NameContext sNC; /* Local name-context */ + ExprList *pGroupBy; /* The group by clause */ + + /* If this routine has run before, return immediately. */ + if( p->isResolved ){ + assert( !pOuterNC ); + return SQLITE_OK; + } + p->isResolved = 1; + + /* If there have already been errors, do nothing. */ + if( pParse->nErr>0 ){ + return SQLITE_ERROR; + } + + /* Prepare the select statement. This call will allocate all cursors + ** required to handle the tables and subqueries in the FROM clause. + */ + if( prepSelectStmt(pParse, p) ){ + return SQLITE_ERROR; + } + + /* Resolve the expressions in the LIMIT and OFFSET clauses. These + ** are not allowed to refer to any names, so pass an empty NameContext. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + if( sqlite3ExprResolveNames(&sNC, p->pLimit) || + sqlite3ExprResolveNames(&sNC, p->pOffset) ){ + return SQLITE_ERROR; + } + + /* Set up the local name-context to pass to ExprResolveNames() to + ** resolve the expression-list. + */ + sNC.allowAgg = 1; + sNC.pSrcList = p->pSrc; + sNC.pNext = pOuterNC; + + /* Resolve names in the result set. */ + pEList = p->pEList; + if( !pEList ) return SQLITE_ERROR; + for(i=0; inExpr; i++){ + Expr *pX = pEList->a[i].pExpr; + if( sqlite3ExprResolveNames(&sNC, pX) ){ + return SQLITE_ERROR; + } + } + + /* If there are no aggregate functions in the result-set, and no GROUP BY + ** expression, do not allow aggregates in any of the other expressions. + */ + assert( !p->isAgg ); + pGroupBy = p->pGroupBy; + if( pGroupBy || sNC.hasAgg ){ + p->isAgg = 1; + }else{ + sNC.allowAgg = 0; + } + + /* If a HAVING clause is present, then there must be a GROUP BY clause. + */ + if( p->pHaving && !pGroupBy ){ + sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); + return SQLITE_ERROR; + } + + /* Add the expression list to the name-context before parsing the + ** other expressions in the SELECT statement. This is so that + ** expressions in the WHERE clause (etc.) can refer to expressions by + ** aliases in the result set. + ** + ** Minor point: If this is the case, then the expression will be + ** re-evaluated for each reference to it. + */ + sNC.pEList = p->pEList; + if( sqlite3ExprResolveNames(&sNC, p->pWhere) || + sqlite3ExprResolveNames(&sNC, p->pHaving) ){ + return SQLITE_ERROR; + } + if( p->pPrior==0 ){ + if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){ + return SQLITE_ERROR; + } + } + if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){ + return SQLITE_ERROR; + } + + if( pParse->db->mallocFailed ){ + return SQLITE_NOMEM; + } + + /* Make sure the GROUP BY clause does not contain aggregate functions. + */ + if( pGroupBy ){ + struct ExprList_item *pItem; + + for(i=0, pItem=pGroupBy->a; inExpr; i++, pItem++){ + if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " + "the GROUP BY clause"); + return SQLITE_ERROR; + } + } + } + + /* If this is one SELECT of a compound, be sure to resolve names + ** in the other SELECTs. + */ + if( p->pPrior ){ + return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC); + }else{ + return SQLITE_OK; + } +} + +/* +** Reset the aggregate accumulator. +** +** The aggregate accumulator is a set of memory cells that hold +** intermediate results while calculating an aggregate. This +** routine simply stores NULLs in all of those memory cells. +*/ +static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pFunc; + if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ + return; + } + for(i=0; inColumn; i++){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem); + } + for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem); + if( pFunc->iDistinct>=0 ){ + Expr *pE = pFunc->pExpr; + if( pE->pList==0 || pE->pList->nExpr!=1 ){ + sqlite3ErrorMsg(pParse, "DISTINCT in aggregate must be followed " + "by an expression"); + pFunc->iDistinct = -1; + }else{ + KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + } + } + } +} + +/* +** Invoke the OP_AggFinalize opcode for every aggregate function +** in the AggInfo structure. +*/ +static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pF; + for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ + ExprList *pList = pF->pExpr->pList; + sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0, + (void*)pF->pFunc, P4_FUNCDEF); + } +} + +/* +** Update the accumulator memory cells for an aggregate based on +** the current cursor position. +*/ +static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pF; + struct AggInfo_col *pC; + + pAggInfo->directMode = 1; + for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ + int nArg; + int addrNext = 0; + int regAgg; + ExprList *pList = pF->pExpr->pList; + if( pList ){ + nArg = pList->nExpr; + regAgg = sqlite3GetTempRange(pParse, nArg); + sqlite3ExprCodeExprList(pParse, pList, regAgg); + }else{ + nArg = 0; + regAgg = 0; + } + if( pF->iDistinct>=0 ){ + addrNext = sqlite3VdbeMakeLabel(v); + assert( nArg==1 ); + codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); + } + if( pF->pFunc->needCollSeq ){ + CollSeq *pColl = 0; + struct ExprList_item *pItem; + int j; + assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */ + for(j=0, pItem=pList->a; !pColl && jpExpr); + } + if( !pColl ){ + pColl = pParse->db->pDfltColl; + } + sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + } + sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, + (void*)pF->pFunc, P4_FUNCDEF); + sqlite3VdbeChangeP5(v, nArg); + sqlite3ReleaseTempRange(pParse, regAgg, nArg); + if( addrNext ){ + sqlite3VdbeResolveLabel(v, addrNext); + } + } + for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ + sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); + } + pAggInfo->directMode = 0; +} + +#ifndef SQLITE_OMIT_TRIGGER +/* +** This function is used when a SELECT statement is used to create a +** temporary table for iterating through when running an INSTEAD OF +** UPDATE or INSTEAD OF DELETE trigger. +** +** If possible, the SELECT statement is modified so that NULL values +** are stored in the temporary table for all columns for which the +** corresponding bit in argument mask is not set. If mask takes the +** special value 0xffffffff, then all columns are populated. +*/ +void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){ + if( p && !p->pPrior && !p->isDistinct && mask!=0xffffffff ){ + ExprList *pEList; + int i; + sqlite3SelectResolve(pParse, p, 0); + pEList = p->pEList; + for(i=0; pEList && inExpr && i<32; i++){ + if( !(mask&((u32)1<a[i].pExpr); + pEList->a[i].pExpr = sqlite3Expr(pParse->db, TK_NULL, 0, 0, 0); + } + } + } +} +#endif + +/* +** Generate code for the given SELECT statement. +** +** The results are distributed in various ways depending on the +** contents of the SelectDest structure pointed to by argument pDest +** as follows: +** +** pDest->eDest Result +** ------------ ------------------------------------------- +** SRT_Callback Invoke the callback for each row of the result. +** +** SRT_Mem Store first result in memory cell pDest->iParm +** +** SRT_Set Store non-null results as keys of table pDest->iParm. +** Apply the affinity pDest->affinity before storing them. +** +** SRT_Union Store results as a key in a temporary table pDest->iParm. +** +** SRT_Except Remove results from the temporary table pDest->iParm. +** +** SRT_Table Store results in temporary table pDest->iParm +** +** SRT_EphemTab Create an temporary table pDest->iParm and store +** the result there. The cursor is left open after +** returning. +** +** SRT_Subroutine For each row returned, push the results onto the +** vdbe stack and call the subroutine (via OP_Gosub) +** at address pDest->iParm. +** +** SRT_Exists Store a 1 in memory cell pDest->iParm if the result +** set is not empty. +** +** SRT_Discard Throw the results away. +** +** See the selectInnerLoop() function for a canonical listing of the +** allowed values of eDest and their meanings. +** +** This routine returns the number of errors. If any errors are +** encountered, then an appropriate error message is left in +** pParse->zErrMsg. +** +** This routine does NOT free the Select structure passed in. The +** calling function needs to do that. +** +** The pParent, parentTab, and *pParentAgg fields are filled in if this +** SELECT is a subquery. This routine may try to combine this SELECT +** with its parent to form a single flat query. In so doing, it might +** change the parent query from a non-aggregate to an aggregate query. +** For that reason, the pParentAgg flag is passed as a pointer, so it +** can be changed. +** +** Example 1: The meaning of the pParent parameter. +** +** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3; +** \ \_______ subquery _______/ / +** \ / +** \____________________ outer query ___________________/ +** +** This routine is called for the outer query first. For that call, +** pParent will be NULL. During the processing of the outer query, this +** routine is called recursively to handle the subquery. For the recursive +** call, pParent will point to the outer query. Because the subquery is +** the second element in a three-way join, the parentTab parameter will +** be 1 (the 2nd value of a 0-indexed array.) +*/ +int sqlite3Select( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + SelectDest *pDest, /* What to do with the query results */ + Select *pParent, /* Another SELECT for which this is a sub-query */ + int parentTab, /* Index in pParent->pSrc of this query */ + int *pParentAgg, /* True if pParent uses aggregate functions */ + char *aff /* If eDest is SRT_Union, the affinity string */ +){ + int i, j; /* Loop counters */ + WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ + Vdbe *v; /* The virtual machine under construction */ + int isAgg; /* True for select lists like "count(*)" */ + ExprList *pEList; /* List of columns to extract. */ + SrcList *pTabList; /* List of tables to select from */ + Expr *pWhere; /* The WHERE clause. May be NULL */ + ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ + ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ + Expr *pHaving; /* The HAVING clause. May be NULL */ + int isDistinct; /* True if the DISTINCT keyword is present */ + int distinct; /* Table to use for the distinct set */ + int rc = 1; /* Value to return from this function */ + int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ + AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ + sqlite3 *db; /* The database connection */ + + db = pParse->db; + if( p==0 || db->mallocFailed || pParse->nErr ){ + return 1; + } + if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + memset(&sAggInfo, 0, sizeof(sAggInfo)); + + pOrderBy = p->pOrderBy; + if( IgnorableOrderby(pDest) ){ + p->pOrderBy = 0; + + /* In these cases the DISTINCT operator makes no difference to the + ** results, so remove it if it were specified. + */ + assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || + pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard); + p->isDistinct = 0; + } + if( sqlite3SelectResolve(pParse, p, 0) ){ + goto select_end; + } + p->pOrderBy = pOrderBy; + +#ifndef SQLITE_OMIT_COMPOUND_SELECT + /* If there is are a sequence of queries, do the earlier ones first. + */ + if( p->pPrior ){ + if( p->pRightmost==0 ){ + Select *pLoop, *pRight = 0; + int cnt = 0; + for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){ + pLoop->pRightmost = p; + pLoop->pNext = pRight; + pRight = pLoop; + } + if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){ + sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); + return 1; + } + } + return multiSelect(pParse, p, pDest, aff); + } +#endif + + /* Make local copies of the parameters for this query. + */ + pTabList = p->pSrc; + pWhere = p->pWhere; + pGroupBy = p->pGroupBy; + pHaving = p->pHaving; + isAgg = p->isAgg; + isDistinct = p->isDistinct; + pEList = p->pEList; + if( pEList==0 ) goto select_end; + + /* + ** Do not even attempt to generate any code if we have already seen + ** errors before this routine starts. + */ + if( pParse->nErr>0 ) goto select_end; + + /* If writing to memory or generating a set + ** only a single column may be output. + */ +#ifndef SQLITE_OMIT_SUBQUERY + if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ + goto select_end; + } +#endif + + /* ORDER BY is ignored for some destinations. + */ + if( IgnorableOrderby(pDest) ){ + pOrderBy = 0; + } + + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto select_end; + + /* Generate code for all sub-queries in the FROM clause + */ +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + for(i=0; inSrc; i++){ + const char *zSavedAuthContext = 0; + int needRestoreContext; + struct SrcList_item *pItem = &pTabList->a[i]; + SelectDest dest; + + if( pItem->pSelect==0 || pItem->isPopulated ) continue; + if( pItem->zName!=0 ){ + zSavedAuthContext = pParse->zAuthContext; + pParse->zAuthContext = pItem->zName; + needRestoreContext = 1; + }else{ + needRestoreContext = 0; + } +#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 + /* Increment Parse.nHeight by the height of the largest expression + ** tree refered to by this, the parent select. The child select + ** may contain expression trees of at most + ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit + ** more conservative than necessary, but much easier than enforcing + ** an exact limit. + */ + pParse->nHeight += sqlite3SelectExprHeight(p); +#endif + sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); + sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0); + if( db->mallocFailed ){ + goto select_end; + } +#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 + pParse->nHeight -= sqlite3SelectExprHeight(p); +#endif + if( needRestoreContext ){ + pParse->zAuthContext = zSavedAuthContext; + } + pTabList = p->pSrc; + pWhere = p->pWhere; + if( !IgnorableOrderby(pDest) ){ + pOrderBy = p->pOrderBy; + } + pGroupBy = p->pGroupBy; + pHaving = p->pHaving; + isDistinct = p->isDistinct; + } +#endif + + /* Check for the special case of a min() or max() function by itself + ** in the result set. + */ +#if 0 + if( simpleMinMaxQuery(pParse, p, pDest) ){ + rc = 0; + goto select_end; + } +#endif + + /* Check to see if this is a subquery that can be "flattened" into its parent. + ** If flattening is a possiblity, do so and return immediately. + */ +#ifndef SQLITE_OMIT_VIEW + if( pParent && pParentAgg && + flattenSubquery(db, pParent, parentTab, *pParentAgg, isAgg) ){ + if( isAgg ) *pParentAgg = 1; + goto select_end; + } +#endif + + /* If possible, rewrite the query to use GROUP BY instead of DISTINCT. + ** GROUP BY may use an index, DISTINCT never does. + */ + if( p->isDistinct && !p->isAgg && !p->pGroupBy ){ + p->pGroupBy = sqlite3ExprListDup(db, p->pEList); + pGroupBy = p->pGroupBy; + p->isDistinct = 0; + isDistinct = 0; + } + + /* If there is an ORDER BY clause, then this sorting + ** index might end up being unused if the data can be + ** extracted in pre-sorted order. If that is the case, then the + ** OP_OpenEphemeral instruction will be changed to an OP_Noop once + ** we figure out that the sorting index is not needed. The addrSortIndex + ** variable is used to facilitate that change. + */ + if( pOrderBy ){ + KeyInfo *pKeyInfo; + pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); + pOrderBy->iECursor = pParse->nTab++; + p->addrOpenEphm[2] = addrSortIndex = + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, + pOrderBy->iECursor, pOrderBy->nExpr+2, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + }else{ + addrSortIndex = -1; + } + + /* If the output is destined for a temporary table, open that table. + */ + if( pDest->eDest==SRT_EphemTab ){ + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr); + } + + /* Set the limiter. + */ + iEnd = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iEnd); + + /* Open a virtual index to use for the distinct set. + */ + if( isDistinct ){ + KeyInfo *pKeyInfo; + assert( isAgg || pGroupBy ); + distinct = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, p->pEList); + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + }else{ + distinct = -1; + } + + /* Aggregate and non-aggregate queries are handled differently */ + if( !isAgg && pGroupBy==0 ){ + /* This case is for non-aggregate queries + ** Begin the database scan + */ + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0); + if( pWInfo==0 ) goto select_end; + + /* If sorting index that was created by a prior OP_OpenEphemeral + ** instruction ended up not being needed, then change the OP_OpenEphemeral + ** into an OP_Noop. + */ + if( addrSortIndex>=0 && pOrderBy==0 ){ + sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); + p->addrOpenEphm[2] = -1; + } + + /* Use the standard inner loop + */ + assert(!isDistinct); + selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest, + pWInfo->iContinue, pWInfo->iBreak, aff); + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + }else{ + /* This is the processing for aggregate queries */ + NameContext sNC; /* Name context for processing aggregate information */ + int iAMem; /* First Mem address for storing current GROUP BY */ + int iBMem; /* First Mem address for previous GROUP BY */ + int iUseFlag; /* Mem address holding flag indicating that at least + ** one row of the input to the aggregator has been + ** processed */ + int iAbortFlag; /* Mem address which causes query abort if positive */ + int groupBySort; /* Rows come from source in GROUP BY order */ + + + /* The following variables hold addresses or labels for parts of the + ** virtual machine program we are putting together */ + int addrOutputRow; /* Start of subroutine that outputs a result row */ + int addrSetAbort; /* Set the abort flag and return */ + int addrInitializeLoop; /* Start of code that initializes the input loop */ + int addrTopOfLoop; /* Top of the input loop */ + int addrGroupByChange; /* Code that runs when any GROUP BY term changes */ + int addrProcessRow; /* Code to process a single input row */ + int addrEnd; /* End of all processing */ + int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ + int addrReset; /* Subroutine for resetting the accumulator */ + + addrEnd = sqlite3VdbeMakeLabel(v); + + /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in + ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the + ** SELECT statement. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + sNC.pAggInfo = &sAggInfo; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; + sAggInfo.pGroupBy = pGroupBy; + sqlite3ExprAnalyzeAggList(&sNC, pEList); + sqlite3ExprAnalyzeAggList(&sNC, pOrderBy); + if( pHaving ){ + sqlite3ExprAnalyzeAggregates(&sNC, pHaving); + } + sAggInfo.nAccumulator = sAggInfo.nColumn; + for(i=0; ipList); + } + if( db->mallocFailed ) goto select_end; + + /* Processing for aggregates with GROUP BY is very different and + ** much more complex than aggregates without a GROUP BY. + */ + if( pGroupBy ){ + KeyInfo *pKeyInfo; /* Keying information for the group by clause */ + + /* Create labels that we will be needing + */ + + addrInitializeLoop = sqlite3VdbeMakeLabel(v); + addrGroupByChange = sqlite3VdbeMakeLabel(v); + addrProcessRow = sqlite3VdbeMakeLabel(v); + + /* If there is a GROUP BY clause we might need a sorting index to + ** implement it. Allocate that sorting index now. If it turns out + ** that we do not need it after all, the OpenEphemeral instruction + ** will be converted into a Noop. + */ + sAggInfo.sortingIdx = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); + addrSortingIdx = + sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sAggInfo.sortingIdx, + sAggInfo.nSortingColumn, 0, + (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + + /* Initialize memory locations used by GROUP BY aggregate processing + */ + iUseFlag = ++pParse->nMem; + iAbortFlag = ++pParse->nMem; + iAMem = pParse->nMem + 1; + pParse->nMem += pGroupBy->nExpr; + iBMem = pParse->nMem + 1; + pParse->nMem += pGroupBy->nExpr; + sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); + VdbeComment((v, "clear abort flag")); + sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); + VdbeComment((v, "indicate accumulator empty")); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInitializeLoop); + + /* Generate a subroutine that outputs a single row of the result + ** set. This subroutine first looks at the iUseFlag. If iUseFlag + ** is less than or equal to zero, the subroutine is a no-op. If + ** the processing calls for the query to abort, this subroutine + ** increments the iAbortFlag memory location before returning in + ** order to signal the caller to abort. + */ + addrSetAbort = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag); + VdbeComment((v, "set abort flag")); + sqlite3VdbeAddOp2(v, OP_Return, 0, 0); + addrOutputRow = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); + VdbeComment((v, "Groupby result generator entry point")); + sqlite3VdbeAddOp2(v, OP_Return, 0, 0); + finalizeAggFunctions(pParse, &sAggInfo); + if( pHaving ){ + sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); + } + selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, + distinct, pDest, + addrOutputRow+1, addrSetAbort, aff); + sqlite3VdbeAddOp2(v, OP_Return, 0, 0); + VdbeComment((v, "end groupby result generator")); + + /* Generate a subroutine that will reset the group-by accumulator + */ + addrReset = sqlite3VdbeCurrentAddr(v); + resetAccumulator(pParse, &sAggInfo); + sqlite3VdbeAddOp2(v, OP_Return, 0, 0); + + /* Begin a loop that will extract all source rows in GROUP BY order. + ** This might involve two separate loops with an OP_Sort in between, or + ** it might be a single loop that uses an index to extract information + ** in the right order to begin with. + */ + sqlite3VdbeResolveLabel(v, addrInitializeLoop); + sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0); + if( pWInfo==0 ) goto select_end; + if( pGroupBy==0 ){ + /* The optimizer is able to deliver rows in group by order so + ** we do not have to sort. The OP_OpenEphemeral table will be + ** cancelled later because we still need to use the pKeyInfo + */ + pGroupBy = p->pGroupBy; + groupBySort = 0; + }else{ + /* Rows are coming out in undetermined order. We have to push + ** each row into a sorting index, terminate the first loop, + ** then loop over the sorting index in order to get the output + ** in sorted order + */ + int regBase; + int regRecord; + int nCol; + int nGroupBy; + + groupBySort = 1; + nGroupBy = pGroupBy->nExpr; + nCol = nGroupBy + 1; + j = nGroupBy+1; + for(i=0; i=j ){ + nCol++; + j++; + } + } + regBase = sqlite3GetTempRange(pParse, nCol); + sqlite3ExprCodeExprList(pParse, pGroupBy, regBase); + sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy); + j = nGroupBy+1; + for(i=0; iiSorterColumn>=j ){ + sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable, + j + regBase); + j++; + } + } + regRecord = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); + sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord); + sqlite3ReleaseTempReg(pParse, regRecord); + sqlite3ReleaseTempRange(pParse, regBase, nCol); + sqlite3WhereEnd(pWInfo); + sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); + VdbeComment((v, "GROUP BY sort")); + sAggInfo.useSortingIdx = 1; + } + + /* Evaluate the current GROUP BY terms and store in b0, b1, b2... + ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) + ** Then compare the current GROUP BY terms against the GROUP BY terms + ** from the previous row currently stored in a0, a1, a2... + */ + addrTopOfLoop = sqlite3VdbeCurrentAddr(v); + for(j=0; jnExpr; j++){ + if( groupBySort ){ + sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem+j); + }else{ + sAggInfo.directMode = 1; + sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); + } + } + for(j=pGroupBy->nExpr-1; j>=0; j--){ + if( j==0 ){ + sqlite3VdbeAddOp3(v, OP_Eq, iAMem+j, addrProcessRow, iBMem+j); + }else{ + sqlite3VdbeAddOp3(v, OP_Ne, iAMem+j, addrGroupByChange, iBMem+j); + } + sqlite3VdbeChangeP4(v, -1, (void*)pKeyInfo->aColl[j], P4_COLLSEQ); + sqlite3VdbeChangeP5(v, SQLITE_NULLEQUAL); + } + + /* Generate code that runs whenever the GROUP BY changes. + ** Change in the GROUP BY are detected by the previous code + ** block. If there were no changes, this block is skipped. + ** + ** This code copies current group by terms in b0,b1,b2,... + ** over to a0,a1,a2. It then calls the output subroutine + ** and resets the aggregate accumulator registers in preparation + ** for the next GROUP BY batch. + */ + sqlite3VdbeResolveLabel(v, addrGroupByChange); + for(j=0; jnExpr; j++){ + sqlite3VdbeAddOp2(v, OP_Move, iBMem+j, iAMem+j); + } + sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow); + VdbeComment((v, "output one row")); + sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); + VdbeComment((v, "check abort flag")); + sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset); + VdbeComment((v, "reset accumulator")); + + /* Update the aggregate accumulators based on the content of + ** the current row + */ + sqlite3VdbeResolveLabel(v, addrProcessRow); + updateAccumulator(pParse, &sAggInfo); + sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); + VdbeComment((v, "indicate data in accumulator")); + + /* End of the loop + */ + if( groupBySort ){ + sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); + }else{ + sqlite3WhereEnd(pWInfo); + sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1); + } + + /* Output the final row of result + */ + sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow); + VdbeComment((v, "output final row")); + + } /* endif pGroupBy */ + else { + ExprList *pMinMax = 0; + ExprList *pDel = 0; + u8 flag; + + /* Check if the query is of one of the following forms: + ** + ** SELECT min(x) FROM ... + ** SELECT max(x) FROM ... + ** + ** If it is, then ask the code in where.c to attempt to sort results + ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. + ** If where.c is able to produce results sorted in this order, then + ** add vdbe code to break out of the processing loop after the + ** first iteration (since the first iteration of the loop is + ** guaranteed to operate on the row with the minimum or maximum + ** value of x, the only row required). + ** + ** A special flag must be passed to sqlite3WhereBegin() to slightly + ** modify behaviour as follows: + ** + ** + If the query is a "SELECT min(x)", then the loop coded by + ** where.c should not iterate over any values with a NULL value + ** for x. + ** + ** + The optimizer code in where.c (the thing that decides which + ** index or indices to use) should place a different priority on + ** satisfying the 'ORDER BY' clause than it does in other cases. + ** Refer to code and comments in where.c for details. + */ + flag = minMaxQuery(pParse, p); + if( flag ){ + pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList); + if( pMinMax && !db->mallocFailed ){ + pMinMax->a[0].sortOrder = ((flag==ORDERBY_MIN)?0:1); + pMinMax->a[0].pExpr->op = TK_COLUMN; + } + } + + /* This case runs if the aggregate has no GROUP BY clause. The + ** processing is much simpler since there is only a single row + ** of output. + */ + resetAccumulator(pParse, &sAggInfo); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag); + if( pWInfo==0 ){ + sqlite3ExprListDelete(pDel); + goto select_end; + } + updateAccumulator(pParse, &sAggInfo); + if( !pMinMax && flag ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak); + VdbeComment((v, "%s() by index", (flag==ORDERBY_MIN?"min":"max"))); + } + sqlite3WhereEnd(pWInfo); + finalizeAggFunctions(pParse, &sAggInfo); + pOrderBy = 0; + if( pHaving ){ + sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); + } + selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, + pDest, addrEnd, addrEnd, aff); + + sqlite3ExprListDelete(pDel); + } + sqlite3VdbeResolveLabel(v, addrEnd); + + } /* endif aggregate query */ + + /* If there is an ORDER BY clause, then we need to sort the results + ** and send them to the callback one by one. + */ + if( pOrderBy ){ + generateSortTail(pParse, p, v, pEList->nExpr, pDest); + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If this was a subquery, we have now converted the subquery into a + ** temporary table. So set the SrcList_item.isPopulated flag to prevent + ** this subquery from being evaluated again and to force the use of + ** the temporary table. + */ + if( pParent ){ + assert( pParent->pSrc->nSrc>parentTab ); + assert( pParent->pSrc->a[parentTab].pSelect==p ); + pParent->pSrc->a[parentTab].isPopulated = 1; + } +#endif + + /* Jump here to skip this query + */ + sqlite3VdbeResolveLabel(v, iEnd); + + /* The SELECT was successfully coded. Set the return code to 0 + ** to indicate no errors. + */ + rc = 0; + + /* Control jumps to here if an error is encountered above, or upon + ** successful coding of the SELECT. + */ +select_end: + + /* Identify column names if we will be using them in a callback. This + ** step is skipped if the output is going to some other destination. + */ + if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){ + generateColumnNames(pParse, pTabList, pEList); + } + + sqlite3_free(sAggInfo.aCol); + sqlite3_free(sAggInfo.aFunc); + return rc; +} + +#if defined(SQLITE_DEBUG) +/* +******************************************************************************* +** The following code is used for testing and debugging only. The code +** that follows does not appear in normal builds. +** +** These routines are used to print out the content of all or part of a +** parse structures such as Select or Expr. Such printouts are useful +** for helping to understand what is happening inside the code generator +** during the execution of complex SELECT statements. +** +** These routine are not called anywhere from within the normal +** code base. Then are intended to be called from within the debugger +** or from temporary "printf" statements inserted for debugging. +*/ +void sqlite3PrintExpr(Expr *p){ + if( p->token.z && p->token.n>0 ){ + sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z); + }else{ + sqlite3DebugPrintf("(%d", p->op); + } + if( p->pLeft ){ + sqlite3DebugPrintf(" "); + sqlite3PrintExpr(p->pLeft); + } + if( p->pRight ){ + sqlite3DebugPrintf(" "); + sqlite3PrintExpr(p->pRight); + } + sqlite3DebugPrintf(")"); +} +void sqlite3PrintExprList(ExprList *pList){ + int i; + for(i=0; inExpr; i++){ + sqlite3PrintExpr(pList->a[i].pExpr); + if( inExpr-1 ){ + sqlite3DebugPrintf(", "); + } + } +} +void sqlite3PrintSelect(Select *p, int indent){ + sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p); + sqlite3PrintExprList(p->pEList); + sqlite3DebugPrintf("\n"); + if( p->pSrc ){ + char *zPrefix; + int i; + zPrefix = "FROM"; + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + sqlite3DebugPrintf("%*s ", indent+6, zPrefix); + zPrefix = ""; + if( pItem->pSelect ){ + sqlite3DebugPrintf("(\n"); + sqlite3PrintSelect(pItem->pSelect, indent+10); + sqlite3DebugPrintf("%*s)", indent+8, ""); + }else if( pItem->zName ){ + sqlite3DebugPrintf("%s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3DebugPrintf("(table: %s)", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3DebugPrintf(" AS %s", pItem->zAlias); + } + if( ipSrc->nSrc-1 ){ + sqlite3DebugPrintf(","); + } + sqlite3DebugPrintf("\n"); + } + } + if( p->pWhere ){ + sqlite3DebugPrintf("%*s WHERE ", indent, ""); + sqlite3PrintExpr(p->pWhere); + sqlite3DebugPrintf("\n"); + } + if( p->pGroupBy ){ + sqlite3DebugPrintf("%*s GROUP BY ", indent, ""); + sqlite3PrintExprList(p->pGroupBy); + sqlite3DebugPrintf("\n"); + } + if( p->pHaving ){ + sqlite3DebugPrintf("%*s HAVING ", indent, ""); + sqlite3PrintExpr(p->pHaving); + sqlite3DebugPrintf("\n"); + } + if( p->pOrderBy ){ + sqlite3DebugPrintf("%*s ORDER BY ", indent, ""); + sqlite3PrintExprList(p->pOrderBy); + sqlite3DebugPrintf("\n"); + } +} +/* End of the structure debug printing code +*****************************************************************************/ +#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/server.c b/client/src/thirdparty/sqlite-3.4.2/src/server.c new file mode 100644 index 0000000..d32c590 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/server.c @@ -0,0 +1,485 @@ +/* +** 2006 January 07 +** +** 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 demonstration code. Nothing in this file gets compiled +** or linked into the SQLite library unless you use a non-standard option: +** +** -DSQLITE_SERVER=1 +** +** The configure script will never generate a Makefile with the option +** above. You will need to manually modify the Makefile if you want to +** include any of the code from this file in your project. Or, at your +** option, you may copy and paste the code from this file and +** thereby avoiding a recompile of SQLite. +** +** +** This source file demonstrates how to use SQLite to create an SQL database +** server thread in a multiple-threaded program. One or more client threads +** send messages to the server thread and the server thread processes those +** messages in the order received and returns the results to the client. +** +** One might ask: "Why bother? Why not just let each thread connect +** to the database directly?" There are a several of reasons to +** prefer the client/server approach. +** +** (1) Some systems (ex: Redhat9) have broken threading implementations +** that prevent SQLite database connections from being used in +** a thread different from the one where they were created. With +** the client/server approach, all database connections are created +** and used within the server thread. Client calls to the database +** can be made from multiple threads (though not at the same time!) +** +** (2) Beginning with SQLite version 3.3.0, when two or more +** connections to the same database occur within the same thread, +** they can optionally share their database cache. This reduces +** I/O and memory requirements. Cache shared is controlled using +** the sqlite3_enable_shared_cache() API. +** +** (3) Database connections on a shared cache use table-level locking +** instead of file-level locking for improved concurrency. +** +** (4) Database connections on a shared cache can by optionally +** set to READ UNCOMMITTED isolation. (The default isolation for +** SQLite is SERIALIZABLE.) When this occurs, readers will +** never be blocked by a writer and writers will not be +** blocked by readers. There can still only be a single writer +** at a time, but multiple readers can simultaneously exist with +** that writer. This is a huge increase in concurrency. +** +** To summarize the rational for using a client/server approach: prior +** to SQLite version 3.3.0 it probably was not worth the trouble. But +** with SQLite version 3.3.0 and beyond you can get significant performance +** and concurrency improvements and memory usage reductions by going +** client/server. +** +** Note: The extra features of version 3.3.0 described by points (2) +** through (4) above are only available if you compile without the +** option -DSQLITE_OMIT_SHARED_CACHE. +** +** Here is how the client/server approach works: The database server +** thread is started on this procedure: +** +** void *sqlite3_server(void *NotUsed); +** +** The sqlite_server procedure runs as long as the g.serverHalt variable +** is false. A mutex is used to make sure no more than one server runs +** at a time. The server waits for messages to arrive on a message +** queue and processes the messages in order. +** +** Two convenience routines are provided for starting and stopping the +** server thread: +** +** void sqlite3_server_start(void); +** void sqlite3_server_stop(void); +** +** Both of the convenience routines return immediately. Neither will +** ever give an error. If a server is already started or already halted, +** then the routines are effectively no-ops. +** +** Clients use the following interfaces: +** +** sqlite3_client_open +** sqlite3_client_prepare +** sqlite3_client_step +** sqlite3_client_reset +** sqlite3_client_finalize +** sqlite3_client_close +** +** These interfaces work exactly like the standard core SQLite interfaces +** having the same names without the "_client_" infix. Many other SQLite +** interfaces can be used directly without having to send messages to the +** server as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. +** The following interfaces fall into this second category: +** +** sqlite3_bind_* +** sqlite3_changes +** sqlite3_clear_bindings +** sqlite3_column_* +** sqlite3_complete +** sqlite3_create_collation +** sqlite3_create_function +** sqlite3_data_count +** sqlite3_db_handle +** sqlite3_errcode +** sqlite3_errmsg +** sqlite3_last_insert_rowid +** sqlite3_total_changes +** sqlite3_transfer_bindings +** +** A single SQLite connection (an sqlite3* object) or an SQLite statement +** (an sqlite3_stmt* object) should only be passed to a single interface +** function at a time. The connections and statements can be passed from +** any thread to any of the functions listed in the second group above as +** long as the same connection is not in use by two threads at once and +** as long as SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined. Additional +** information about the SQLITE_ENABLE_MEMORY_MANAGEMENT constraint is +** below. +** +** The busy handler for all database connections should remain turned +** off. That means that any lock contention will cause the associated +** sqlite3_client_step() call to return immediately with an SQLITE_BUSY +** error code. If a busy handler is enabled and lock contention occurs, +** then the entire server thread will block. This will cause not only +** the requesting client to block but every other database client as +** well. It is possible to enhance the code below so that lock +** contention will cause the message to be placed back on the top of +** the queue to be tried again later. But such enhanced processing is +** not included here, in order to keep the example simple. +** +** This example code assumes the use of pthreads. Pthreads +** implementations are available for windows. (See, for example +** http://sourceware.org/pthreads-win32/announcement.html.) Or, you +** can translate the locking and thread synchronization code to use +** windows primitives easily enough. The details are left as an +** exercise to the reader. +** +**** Restrictions Associated With SQLITE_ENABLE_MEMORY_MANAGEMENT **** +** +** If you compile with SQLITE_ENABLE_MEMORY_MANAGEMENT defined, then +** SQLite includes code that tracks how much memory is being used by +** each thread. These memory counts can become confused if memory +** is allocated by one thread and then freed by another. For that +** reason, when SQLITE_ENABLE_MEMORY_MANAGEMENT is used, all operations +** that might allocate or free memory should be performanced in the same +** thread that originally created the database connection. In that case, +** many of the operations that are listed above as safe to be performed +** in separate threads would need to be sent over to the server to be +** done there. If SQLITE_ENABLE_MEMORY_MANAGEMENT is defined, then +** the following functions can be used safely from different threads +** without messing up the allocation counts: +** +** sqlite3_bind_parameter_name +** sqlite3_bind_parameter_index +** sqlite3_changes +** sqlite3_column_blob +** sqlite3_column_count +** sqlite3_complete +** sqlite3_data_count +** sqlite3_db_handle +** sqlite3_errcode +** sqlite3_errmsg +** sqlite3_last_insert_rowid +** sqlite3_total_changes +** +** The remaining functions are not thread-safe when memory management +** is enabled. So one would have to define some new interface routines +** along the following lines: +** +** sqlite3_client_bind_* +** sqlite3_client_clear_bindings +** sqlite3_client_column_* +** sqlite3_client_create_collation +** sqlite3_client_create_function +** sqlite3_client_transfer_bindings +** +** The example code in this file is intended for use with memory +** management turned off. So the implementation of these additional +** client interfaces is left as an exercise to the reader. +** +** It may seem surprising to the reader that the list of safe functions +** above does not include things like sqlite3_bind_int() or +** sqlite3_column_int(). But those routines might, in fact, allocate +** or deallocate memory. In the case of sqlite3_bind_int(), if the +** parameter was previously bound to a string that string might need +** to be deallocated before the new integer value is inserted. In +** the case of sqlite3_column_int(), the value of the column might be +** a UTF-16 string which will need to be converted to UTF-8 then into +** an integer. +*/ + +/* +** Only compile the code in this file on UNIX with a THREADSAFE build +** and only if the SQLITE_SERVER macro is defined. +*/ +#ifdef SQLITE_SERVER +#if defined(OS_UNIX) && OS_UNIX && defined(THREADSAFE) && THREADSAFE + +/* +** We require only pthreads and the public interface of SQLite. +*/ +#include +#include "sqlite3.h" + +/* +** Messages are passed from client to server and back again as +** instances of the following structure. +*/ +typedef struct SqlMessage SqlMessage; +struct SqlMessage { + int op; /* Opcode for the message */ + sqlite3 *pDb; /* The SQLite connection */ + sqlite3_stmt *pStmt; /* A specific statement */ + int errCode; /* Error code returned */ + const char *zIn; /* Input filename or SQL statement */ + int nByte; /* Size of the zIn parameter for prepare() */ + const char *zOut; /* Tail of the SQL statement */ + SqlMessage *pNext; /* Next message in the queue */ + SqlMessage *pPrev; /* Previous message in the queue */ + pthread_mutex_t clientMutex; /* Hold this mutex to access the message */ + pthread_cond_t clientWakeup; /* Signal to wake up the client */ +}; + +/* +** Legal values for SqlMessage.op +*/ +#define MSG_Open 1 /* sqlite3_open(zIn, &pDb) */ +#define MSG_Prepare 2 /* sqlite3_prepare(pDb, zIn, nByte, &pStmt, &zOut) */ +#define MSG_Step 3 /* sqlite3_step(pStmt) */ +#define MSG_Reset 4 /* sqlite3_reset(pStmt) */ +#define MSG_Finalize 5 /* sqlite3_finalize(pStmt) */ +#define MSG_Close 6 /* sqlite3_close(pDb) */ +#define MSG_Done 7 /* Server has finished with this message */ + + +/* +** State information about the server is stored in a static variable +** named "g" as follows: +*/ +static struct ServerState { + pthread_mutex_t queueMutex; /* Hold this mutex to access the msg queue */ + pthread_mutex_t serverMutex; /* Held by the server while it is running */ + pthread_cond_t serverWakeup; /* Signal this condvar to wake up the server */ + volatile int serverHalt; /* Server halts itself when true */ + SqlMessage *pQueueHead; /* Head of the message queue */ + SqlMessage *pQueueTail; /* Tail of the message queue */ +} g = { + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_MUTEX_INITIALIZER, + PTHREAD_COND_INITIALIZER, +}; + +/* +** Send a message to the server. Block until we get a reply. +** +** The mutex and condition variable in the message are uninitialized +** when this routine is called. This routine takes care of +** initializing them and destroying them when it has finished. +*/ +static void sendToServer(SqlMessage *pMsg){ + /* Initialize the mutex and condition variable on the message + */ + pthread_mutex_init(&pMsg->clientMutex, 0); + pthread_cond_init(&pMsg->clientWakeup, 0); + + /* Add the message to the head of the server's message queue. + */ + pthread_mutex_lock(&g.queueMutex); + pMsg->pNext = g.pQueueHead; + if( g.pQueueHead==0 ){ + g.pQueueTail = pMsg; + }else{ + g.pQueueHead->pPrev = pMsg; + } + pMsg->pPrev = 0; + g.pQueueHead = pMsg; + pthread_mutex_unlock(&g.queueMutex); + + /* Signal the server that the new message has be queued, then + ** block waiting for the server to process the message. + */ + pthread_mutex_lock(&pMsg->clientMutex); + pthread_cond_signal(&g.serverWakeup); + while( pMsg->op!=MSG_Done ){ + pthread_cond_wait(&pMsg->clientWakeup, &pMsg->clientMutex); + } + pthread_mutex_unlock(&pMsg->clientMutex); + + /* Destroy the mutex and condition variable of the message. + */ + pthread_mutex_destroy(&pMsg->clientMutex); + pthread_cond_destroy(&pMsg->clientWakeup); +} + +/* +** The following 6 routines are client-side implementations of the +** core SQLite interfaces: +** +** sqlite3_open +** sqlite3_prepare +** sqlite3_step +** sqlite3_reset +** sqlite3_finalize +** sqlite3_close +** +** Clients should use the following client-side routines instead of +** the core routines above. +** +** sqlite3_client_open +** sqlite3_client_prepare +** sqlite3_client_step +** sqlite3_client_reset +** sqlite3_client_finalize +** sqlite3_client_close +** +** Each of these routines creates a message for the desired operation, +** sends that message to the server, waits for the server to process +** then message and return a response. +*/ +int sqlite3_client_open(const char *zDatabaseName, sqlite3 **ppDb){ + SqlMessage msg; + msg.op = MSG_Open; + msg.zIn = zDatabaseName; + sendToServer(&msg); + *ppDb = msg.pDb; + return msg.errCode; +} +int sqlite3_client_prepare( + sqlite3 *pDb, + const char *zSql, + int nByte, + sqlite3_stmt **ppStmt, + const char **pzTail +){ + SqlMessage msg; + msg.op = MSG_Prepare; + msg.pDb = pDb; + msg.zIn = zSql; + msg.nByte = nByte; + sendToServer(&msg); + *ppStmt = msg.pStmt; + if( pzTail ) *pzTail = msg.zOut; + return msg.errCode; +} +int sqlite3_client_step(sqlite3_stmt *pStmt){ + SqlMessage msg; + msg.op = MSG_Step; + msg.pStmt = pStmt; + sendToServer(&msg); + return msg.errCode; +} +int sqlite3_client_reset(sqlite3_stmt *pStmt){ + SqlMessage msg; + msg.op = MSG_Reset; + msg.pStmt = pStmt; + sendToServer(&msg); + return msg.errCode; +} +int sqlite3_client_finalize(sqlite3_stmt *pStmt){ + SqlMessage msg; + msg.op = MSG_Finalize; + msg.pStmt = pStmt; + sendToServer(&msg); + return msg.errCode; +} +int sqlite3_client_close(sqlite3 *pDb){ + SqlMessage msg; + msg.op = MSG_Close; + msg.pDb = pDb; + sendToServer(&msg); + return msg.errCode; +} + +/* +** This routine implements the server. To start the server, first +** make sure g.serverHalt is false, then create a new detached thread +** on this procedure. See the sqlite3_server_start() routine below +** for an example. This procedure loops until g.serverHalt becomes +** true. +*/ +void *sqlite3_server(void *NotUsed){ + sqlite3_enable_shared_cache(1); + if( pthread_mutex_trylock(&g.serverMutex) ){ + sqlite3_enable_shared_cache(0); + return 0; /* Another server is already running */ + } + while( !g.serverHalt ){ + SqlMessage *pMsg; + + /* Remove the last message from the message queue. + */ + pthread_mutex_lock(&g.queueMutex); + while( g.pQueueTail==0 && g.serverHalt==0 ){ + pthread_cond_wait(&g.serverWakeup, &g.queueMutex); + } + pMsg = g.pQueueTail; + if( pMsg ){ + if( pMsg->pPrev ){ + pMsg->pPrev->pNext = 0; + }else{ + g.pQueueHead = 0; + } + g.pQueueTail = pMsg->pPrev; + } + pthread_mutex_unlock(&g.queueMutex); + if( pMsg==0 ) break; + + /* Process the message just removed + */ + pthread_mutex_lock(&pMsg->clientMutex); + switch( pMsg->op ){ + case MSG_Open: { + pMsg->errCode = sqlite3_open(pMsg->zIn, &pMsg->pDb); + break; + } + case MSG_Prepare: { + pMsg->errCode = sqlite3_prepare(pMsg->pDb, pMsg->zIn, pMsg->nByte, + &pMsg->pStmt, &pMsg->zOut); + break; + } + case MSG_Step: { + pMsg->errCode = sqlite3_step(pMsg->pStmt); + break; + } + case MSG_Reset: { + pMsg->errCode = sqlite3_reset(pMsg->pStmt); + break; + } + case MSG_Finalize: { + pMsg->errCode = sqlite3_finalize(pMsg->pStmt); + break; + } + case MSG_Close: { + pMsg->errCode = sqlite3_close(pMsg->pDb); + break; + } + } + + /* Signal the client that the message has been processed. + */ + pMsg->op = MSG_Done; + pthread_mutex_unlock(&pMsg->clientMutex); + pthread_cond_signal(&pMsg->clientWakeup); + } + pthread_mutex_unlock(&g.serverMutex); + sqlite3_thread_cleanup(); + return 0; +} + +/* +** Start a server thread if one is not already running. If there +** is aleady a server thread running, the new thread will quickly +** die and this routine is effectively a no-op. +*/ +void sqlite3_server_start(void){ + pthread_t x; + int rc; + g.serverHalt = 0; + rc = pthread_create(&x, 0, sqlite3_server, 0); + if( rc==0 ){ + pthread_detach(x); + } +} + +/* +** If a server thread is running, then stop it. If no server is +** running, this routine is effectively a no-op. +** +** This routine returns immediately without waiting for the server +** thread to stop. But be assured that the server will eventually stop. +*/ +void sqlite3_server_stop(void){ + g.serverHalt = 1; + pthread_cond_broadcast(&g.serverWakeup); +} + +#endif /* defined(OS_UNIX) && OS_UNIX && defined(THREADSAFE) && THREADSAFE */ +#endif /* defined(SQLITE_SERVER) */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/shell.c b/client/src/thirdparty/sqlite-3.4.2/src/shell.c new file mode 100644 index 0000000..6fe9324 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/shell.c @@ -0,0 +1,2087 @@ +/* +** 2001 September 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. +** +************************************************************************* +** This file contains code to implement the "sqlite" command line +** utility for accessing SQLite databases. +** +** $Id: shell.c,v 1.174 2008/01/21 16:22:46 drh Exp $ +*/ +#include +#include +#include +#include +#include "sqlite3.h" +#include +#include + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) +# include +# include +# include +# include +#endif + +#ifdef __OS2__ +# include +#endif + +#if defined(HAVE_READLINE) && HAVE_READLINE==1 +# include +# include +#else +# define readline(p) local_getline(p,stdin) +# define add_history(X) +# define read_history(X) +# define write_history(X) +# define stifle_history(X) +#endif + +#if defined(_WIN32) || defined(WIN32) +# include +#else +/* Make sure isatty() has a prototype. +*/ +extern int isatty(); +#endif + +#if defined(_WIN32_WCE) +/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() + * thus we always assume that we have a console. That can be + * overridden with the -batch command line option. + */ +#define isatty(x) 1 +#endif + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) +#include +#include + +/* Saved resource information for the beginning of an operation */ +static struct rusage sBegin; + +/* True if the timer is enabled */ +static int enableTimer = 0; + +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + } +} + +/* Return the difference of two time_structs in microseconds */ +static int timeDiff(struct timeval *pStart, struct timeval *pEnd){ + return (pEnd->tv_usec - pStart->tv_usec) + + 1000000*(pEnd->tv_sec - pStart->tv_sec); +} + +/* +** Print the timing results. +*/ +static void endTimer(void){ + if( enableTimer ){ + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + printf("CPU Time: user %f sys %f\n", + 0.000001*timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + 0.000001*timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); + } +} +#define BEGIN_TIMER beginTimer() +#define END_TIMER endTimer() +#define HAS_TIMER 1 +#else +#define BEGIN_TIMER +#define END_TIMER +#define HAS_TIMER 0 +#endif + + +/* +** If the following flag is set, then command execution stops +** at an error if we are not interactive. +*/ +static int bail_on_error = 0; + +/* +** Threat stdin as an interactive input if the following variable +** is true. Otherwise, assume stdin is connected to a file or pipe. +*/ +static int stdin_is_interactive = 1; + +/* +** The following is the open SQLite database. We make a pointer +** to this database a static variable so that it can be accessed +** by the SIGINT handler to interrupt database processing. +*/ +static sqlite3 *db = 0; + +/* +** True if an interrupt (Control-C) has been received. +*/ +static volatile int seenInterrupt = 0; + +/* +** This is the name of our program. It is set in main(), used +** in a number of other places, mostly for error messages. +*/ +static char *Argv0; + +/* +** Prompt strings. Initialized in main. Settable with +** .prompt main continue +*/ +static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ +static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ + +/* +** Write I/O traces to the following stream. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static FILE *iotrace = 0; +#endif + +/* +** This routine works like printf in that its first argument is a +** format string and subsequent arguments are values to be substituted +** in place of % fields. The result of formatting this string +** is written to iotrace. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static void iotracePrintf(const char *zFormat, ...){ + va_list ap; + char *z; + if( iotrace==0 ) return; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + fprintf(iotrace, "%s", z); + sqlite3_free(z); +} +#endif + + +/* +** Determines if a string is a number of not. +*/ +static int isNumber(const char *z, int *realnum){ + if( *z=='-' || *z=='+' ) z++; + if( !isdigit(*z) ){ + return 0; + } + z++; + if( realnum ) *realnum = 0; + while( isdigit(*z) ){ z++; } + if( *z=='.' ){ + z++; + if( !isdigit(*z) ) return 0; + while( isdigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z++; + if( *z=='+' || *z=='-' ) z++; + if( !isdigit(*z) ) return 0; + while( isdigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + return *z==0; +} + +/* +** A global char* and an SQL function to access its current value +** from within an SQL statement. This program used to use the +** sqlite_exec_printf() API to substitue a string into an SQL statement. +** The correct way to do this with sqlite3 is to use the bind API, but +** since the shell is built around the callback paradigm it would be a lot +** of work. Instead just use this hack, which is quite harmless. +*/ +static const char *zShellStatic = 0; +static void shellstaticFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + assert( 0==argc ); + assert( zShellStatic ); + sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); +} + + +/* +** This routine reads a line of text from FILE in, stores +** the text in memory obtained from malloc() and returns a pointer +** to the text. NULL is returned at end of file, or if malloc() +** fails. +** +** The interface is like "readline" but no command-line editing +** is done. +*/ +static char *local_getline(char *zPrompt, FILE *in){ + char *zLine; + int nLine; + int n; + int eol; + + if( zPrompt && *zPrompt ){ + printf("%s",zPrompt); + fflush(stdout); + } + nLine = 100; + zLine = malloc( nLine ); + if( zLine==0 ) return 0; + n = 0; + eol = 0; + while( !eol ){ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + if( zLine==0 ) return 0; + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; + } + zLine[n] = 0; + eol = 1; + break; + } + while( zLine[n] ){ n++; } + if( n>0 && zLine[n-1]=='\n' ){ + n--; + zLine[n] = 0; + eol = 1; + } + } + zLine = realloc( zLine, n+1 ); + return zLine; +} + +/* +** Retrieve a single line of input text. +** +** zPrior is a string of prior text retrieved. If not the empty +** string, then issue a continuation prompt. +*/ +static char *one_input_line(const char *zPrior, FILE *in){ + char *zPrompt; + char *zResult; + if( in!=0 ){ + return local_getline(0, in); + } + if( zPrior && zPrior[0] ){ + zPrompt = continuePrompt; + }else{ + zPrompt = mainPrompt; + } + zResult = readline(zPrompt); +#if defined(HAVE_READLINE) && HAVE_READLINE==1 + if( zResult && *zResult ) add_history(zResult); +#endif + return zResult; +} + +struct previous_mode_data { + int valid; /* Is there legit data in here? */ + int mode; + int showHeader; + int colWidth[100]; +}; + +/* +** An pointer to an instance of this structure is passed from +** the main program to the callback. This is used to communicate +** state and mode information. +*/ +struct callback_data { + sqlite3 *db; /* The database */ + int echoOn; /* True to echo input commands */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ + int mode; /* An output mode setting */ + int writableSchema; /* True if PRAGMA writable_schema=ON */ + int showHeader; /* True to show column names in List or Column mode */ + char *zDestTable; /* Name of destination table when MODE_Insert */ + char separator[20]; /* Separator character for MODE_List */ + int colWidth[100]; /* Requested width of each column when in column mode*/ + int actualWidth[100]; /* Actual width of each column */ + char nullvalue[20]; /* The text to print when a NULL comes back from + ** the database */ + struct previous_mode_data explainPrev; + /* Holds the mode information just before + ** .explain ON */ + char outfile[FILENAME_MAX]; /* Filename for *out */ + const char *zDbFilename; /* name of the database file */ +}; + +/* +** These are the allowed modes. +*/ +#define MODE_Line 0 /* One column per line. Blank line between records */ +#define MODE_Column 1 /* One record per line in neat columns */ +#define MODE_List 2 /* One record per line with a separator */ +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ +#define MODE_Html 4 /* Generate an XHTML table */ +#define MODE_Insert 5 /* Generate SQL "insert" statements */ +#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ +#define MODE_Csv 7 /* Quote strings, numbers are plain */ +#define MODE_NUM_OF 8 /* The number of modes (not a mode itself) */ +#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */ + +static const char *modeDescr[MODE_NUM_OF] = { + "line", + "column", + "list", + "semi", + "html", + "insert", + "tcl", + "csv", +}; + +/* +** Number of elements in an array +*/ +#define ArraySize(X) (sizeof(X)/sizeof(X[0])) + +/* +** Output the given string as a quoted string using SQL quoting conventions. +*/ +static void output_quoted_string(FILE *out, const char *z){ + int i; + int nSingle = 0; + for(i=0; z[i]; i++){ + if( z[i]=='\'' ) nSingle++; + } + if( nSingle==0 ){ + fprintf(out,"'%s'",z); + }else{ + fprintf(out,"'"); + while( *z ){ + for(i=0; z[i] && z[i]!='\''; i++){} + if( i==0 ){ + fprintf(out,"''"); + z++; + }else if( z[i]=='\'' ){ + fprintf(out,"%.*s''",i,z); + z += i+1; + }else{ + fprintf(out,"%s",z); + break; + } + } + fprintf(out,"'"); + } +} + +/* +** Output the given string as a quoted according to C or TCL quoting rules. +*/ +static void output_c_string(FILE *out, const char *z){ + unsigned int c; + fputc('"', out); + while( (c = *(z++))!=0 ){ + if( c=='\\' ){ + fputc(c, out); + fputc(c, out); + }else if( c=='\t' ){ + fputc('\\', out); + fputc('t', out); + }else if( c=='\n' ){ + fputc('\\', out); + fputc('n', out); + }else if( c=='\r' ){ + fputc('\\', out); + fputc('r', out); + }else if( !isprint(c) ){ + fprintf(out, "\\%03o", c&0xff); + }else{ + fputc(c, out); + } + } + fputc('"', out); +} + +/* +** Output the given string with characters that are special to +** HTML escaped. +*/ +static void output_html_string(FILE *out, const char *z){ + int i; + while( *z ){ + for(i=0; z[i] && z[i]!='<' && z[i]!='&'; i++){} + if( i>0 ){ + fprintf(out,"%.*s",i,z); + } + if( z[i]=='<' ){ + fprintf(out,"<"); + }else if( z[i]=='&' ){ + fprintf(out,"&"); + }else{ + break; + } + z += i + 1; + } +} + +/* +** If a field contains any character identified by a 1 in the following +** array, then the string must be quoted for CSV. +*/ +static const char needCsvQuote[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 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, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +/* +** Output a single term of CSV. Actually, p->separator is used for +** the separator, which may or may not be a comma. p->nullvalue is +** the null value. Strings are quoted using ANSI-C rules. Numbers +** appear outside of quotes. +*/ +static void output_csv(struct callback_data *p, const char *z, int bSep){ + FILE *out = p->out; + if( z==0 ){ + fprintf(out,"%s",p->nullvalue); + }else{ + int i; + int nSep = strlen(p->separator); + for(i=0; z[i]; i++){ + if( needCsvQuote[((unsigned char*)z)[i]] + || (z[i]==p->separator[0] && + (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){ + i = 0; + break; + } + } + if( i==0 ){ + putc('"', out); + for(i=0; z[i]; i++){ + if( z[i]=='"' ) putc('"', out); + putc(z[i], out); + } + putc('"', out); + }else{ + fprintf(out, "%s", z); + } + } + if( bSep ){ + fprintf(p->out, "%s", p->separator); + } +} + +#ifdef SIGINT +/* +** This routine runs when the user presses Ctrl-C +*/ +static void interrupt_handler(int NotUsed){ + seenInterrupt = 1; + if( db ) sqlite3_interrupt(db); +} +#endif + +/* +** This is the callback routine that the SQLite library +** invokes for each row of a query result. +*/ +static int callback(void *pArg, int nArg, char **azArg, char **azCol){ + int i; + struct callback_data *p = (struct callback_data*)pArg; + switch( p->mode ){ + case MODE_Line: { + int w = 5; + if( azArg==0 ) break; + for(i=0; iw ) w = len; + } + if( p->cnt++>0 ) fprintf(p->out,"\n"); + for(i=0; iout,"%*s = %s\n", w, azCol[i], + azArg[i] ? azArg[i] : p->nullvalue); + } + break; + } + case MODE_Explain: + case MODE_Column: { + if( p->cnt++==0 ){ + for(i=0; icolWidth) ){ + w = p->colWidth[i]; + }else{ + w = 0; + } + if( w<=0 ){ + w = strlen(azCol[i] ? azCol[i] : ""); + if( w<10 ) w = 10; + n = strlen(azArg && azArg[i] ? azArg[i] : p->nullvalue); + if( wactualWidth) ){ + p->actualWidth[i] = w; + } + if( p->showHeader ){ + fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); + } + } + if( p->showHeader ){ + for(i=0; iactualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" + "----------------------------------------------------------", + i==nArg-1 ? "\n": " "); + } + } + } + if( azArg==0 ) break; + for(i=0; iactualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + if( p->mode==MODE_Explain && azArg[i] && strlen(azArg[i])>w ){ + w = strlen(azArg[i]); + } + fprintf(p->out,"%-*.*s%s",w,w, + azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); + } + break; + } + case MODE_Semi: + case MODE_List: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); + } + } + if( azArg==0 ) break; + for(i=0; inullvalue; + fprintf(p->out, "%s", z); + if( iout, "%s", p->separator); + }else if( p->mode==MODE_Semi ){ + fprintf(p->out, ";\n"); + }else{ + fprintf(p->out, "\n"); + } + } + break; + } + case MODE_Html: { + if( p->cnt++==0 && p->showHeader ){ + fprintf(p->out,""); + for(i=0; iout,"",azCol[i]); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + fprintf(p->out,""); + for(i=0; iout,"\n"); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Tcl: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,azCol[i] ? azCol[i] : ""); + fprintf(p->out, "%s", p->separator); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + for(i=0; iout, azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out, "%s", p->separator); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Csv: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,"\n"); + } + if( azArg==0 ) break; + for(i=0; iout,"\n"); + break; + } + case MODE_Insert: { + if( azArg==0 ) break; + fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); + for(i=0; i0 ? ",": ""; + if( azArg[i]==0 ){ + fprintf(p->out,"%sNULL",zSep); + }else if( isNumber(azArg[i], 0) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else{ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + } + } + fprintf(p->out,");\n"); + break; + } + } + return 0; +} + +/* +** Set the destination table field of the callback_data structure to +** the name of the table given. Escape any quote characters in the +** table name. +*/ +static void set_table_name(struct callback_data *p, const char *zName){ + int i, n; + int needQuote; + char *z; + + if( p->zDestTable ){ + free(p->zDestTable); + p->zDestTable = 0; + } + if( zName==0 ) return; + needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; + for(i=n=0; zName[i]; i++, n++){ + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ + needQuote = 1; + if( zName[i]=='\'' ) n++; + } + } + if( needQuote ) n += 2; + z = p->zDestTable = malloc( n+1 ); + if( z==0 ){ + fprintf(stderr,"Out of memory!\n"); + exit(1); + } + n = 0; + if( needQuote ) z[n++] = '\''; + for(i=0; zName[i]; i++){ + z[n++] = zName[i]; + if( zName[i]=='\'' ) z[n++] = '\''; + } + if( needQuote ) z[n++] = '\''; + z[n] = 0; +} + +/* zIn is either a pointer to a NULL-terminated string in memory obtained +** from malloc(), or a NULL pointer. The string pointed to by zAppend is +** added to zIn, and the result returned in memory obtained from malloc(). +** zIn, if it was not NULL, is freed. +** +** If the third argument, quote, is not '\0', then it is used as a +** quote character for zAppend. +*/ +static char *appendText(char *zIn, char const *zAppend, char quote){ + int len; + int i; + int nAppend = strlen(zAppend); + int nIn = (zIn?strlen(zIn):0); + + len = nAppend+nIn+1; + if( quote ){ + len += 2; + for(i=0; iout, "DELETE FROM sqlite_sequence;\n"); + }else if( strcmp(zTable, "sqlite_stat1")==0 ){ + fprintf(p->out, "ANALYZE sqlite_master;\n"); + }else if( strncmp(zTable, "sqlite_", 7)==0 ){ + return 0; + }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ + char *zIns; + if( !p->writableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=ON;\n"); + p->writableSchema = 1; + } + zIns = sqlite3_mprintf( + "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','%q','%q',0,'%q');", + zTable, zTable, zSql); + fprintf(p->out, "%s\n", zIns); + sqlite3_free(zIns); + return 0; + }else{ + fprintf(p->out, "%s;\n", zSql); + } + + if( strcmp(zType, "table")==0 ){ + sqlite3_stmt *pTableInfo = 0; + char *zSelect = 0; + char *zTableInfo = 0; + char *zTmp = 0; + + zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); + zTableInfo = appendText(zTableInfo, zTable, '"'); + zTableInfo = appendText(zTableInfo, ");", 0); + + rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); + if( zTableInfo ) free(zTableInfo); + if( rc!=SQLITE_OK || !pTableInfo ){ + return 1; + } + + zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); + zTmp = appendText(zTmp, zTable, '"'); + if( zTmp ){ + zSelect = appendText(zSelect, zTmp, '\''); + } + zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); + rc = sqlite3_step(pTableInfo); + while( rc==SQLITE_ROW ){ + const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); + zSelect = appendText(zSelect, "quote(", 0); + zSelect = appendText(zSelect, zText, '"'); + rc = sqlite3_step(pTableInfo); + if( rc==SQLITE_ROW ){ + zSelect = appendText(zSelect, ") || ',' || ", 0); + }else{ + zSelect = appendText(zSelect, ") ", 0); + } + } + rc = sqlite3_finalize(pTableInfo); + if( rc!=SQLITE_OK ){ + if( zSelect ) free(zSelect); + return 1; + } + zSelect = appendText(zSelect, "|| ')' FROM ", 0); + zSelect = appendText(zSelect, zTable, '"'); + + rc = run_table_dump_query(p->out, p->db, zSelect); + if( rc==SQLITE_CORRUPT ){ + zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); + rc = run_table_dump_query(p->out, p->db, zSelect); + } + if( zSelect ) free(zSelect); + } + return 0; +} + +/* +** Run zQuery. Use dump_callback() as the callback routine so that +** the contents of the query are output as SQL statements. +** +** If we get a SQLITE_CORRUPT error, rerun the query after appending +** "ORDER BY rowid DESC" to the end. +*/ +static int run_schema_dump_query( + struct callback_data *p, + const char *zQuery, + char **pzErrMsg +){ + int rc; + rc = sqlite3_exec(p->db, zQuery, dump_callback, p, pzErrMsg); + if( rc==SQLITE_CORRUPT ){ + char *zQ2; + int len = strlen(zQuery); + if( pzErrMsg ) sqlite3_free(*pzErrMsg); + zQ2 = malloc( len+100 ); + if( zQ2==0 ) return rc; + sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery); + rc = sqlite3_exec(p->db, zQ2, dump_callback, p, pzErrMsg); + free(zQ2); + } + return rc; +} + +/* +** Text of a help message +*/ +static char zHelp[] = + ".bail ON|OFF Stop after hitting an error. Default OFF\n" + ".databases List names and files of attached databases\n" + ".dump ?TABLE? ... Dump the database in an SQL text format\n" + ".echo ON|OFF Turn command echo on or off\n" + ".exit Exit this program\n" + ".explain ON|OFF Turn output mode suitable for EXPLAIN on or off.\n" + ".header(s) 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 on TABLE\n" +#ifdef SQLITE_ENABLE_IOTRACE + ".iotrace FILE Enable I/O diagnostic logging to FILE\n" +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + ".load FILE ?ENTRY? Load an extension library\n" +#endif + ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" + " csv Comma-separated values\n" + " column Left-aligned columns. (See .width)\n" + " html HTML
%s
"); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out,"
code\n" + " insert SQL insert statements for TABLE\n" + " line One value per line\n" + " list Values delimited by .separator string\n" + " tabs Tab-separated values\n" + " tcl TCL list elements\n" + ".nullvalue STRING Print STRING in place of NULL values\n" + ".output FILENAME Send output to FILENAME\n" + ".output stdout Send output to the screen\n" + ".prompt MAIN CONTINUE Replace the standard prompts\n" + ".quit Exit this program\n" + ".read FILENAME Execute SQL in FILENAME\n" + ".schema ?TABLE? Show the CREATE statements\n" + ".separator STRING Change separator used by output mode and .import\n" + ".show Show the current values for various settings\n" + ".tables ?PATTERN? List names of tables matching a LIKE pattern\n" + ".timeout MS Try opening locked tables for MS milliseconds\n" +#if HAS_TIMER + ".timer ON|OFF Turn the CPU timer measurement on or off\n" +#endif + ".width NUM NUM ... Set column widths for \"column\" mode\n" +; + +/* Forward reference */ +static int process_input(struct callback_data *p, FILE *in); + +/* +** Make sure the database is open. If it is not, then open it. If +** the database fails to open, print an error message and exit. +*/ +static void open_db(struct callback_data *p){ + if( p->db==0 ){ + sqlite3_open(p->zDbFilename, &p->db); + db = p->db; + sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, + shellstaticFunc, 0, 0); + if( SQLITE_OK!=sqlite3_errcode(db) ){ + fprintf(stderr,"Unable to open database \"%s\": %s\n", + p->zDbFilename, sqlite3_errmsg(db)); + exit(1); + } +#ifndef SQLITE_OMIT_LOAD_EXTENSION + sqlite3_enable_load_extension(p->db, 1); +#endif + } +} + +/* +** Do C-language style dequoting. +** +** \t -> tab +** \n -> newline +** \r -> carriage return +** \NNN -> ascii character NNN in octal +** \\ -> backslash +*/ +static void resolve_backslashes(char *z){ + int i, j, c; + for(i=j=0; (c = z[i])!=0; i++, j++){ + if( c=='\\' ){ + c = z[++i]; + if( c=='n' ){ + c = '\n'; + }else if( c=='t' ){ + c = '\t'; + }else if( c=='r' ){ + c = '\r'; + }else if( c>='0' && c<='7' ){ + c -= '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + } + } + } + } + z[j] = c; + } + z[j] = 0; +} + +/* +** Interpret zArg as a boolean value. Return either 0 or 1. +*/ +static int booleanValue(char *zArg){ + int val = atoi(zArg); + int j; + for(j=0; zArg[j]; j++){ + zArg[j] = tolower(zArg[j]); + } + if( strcmp(zArg,"on")==0 ){ + val = 1; + }else if( strcmp(zArg,"yes")==0 ){ + val = 1; + } + return val; +} + +/* +** If an input line begins with "." then invoke this routine to +** process that line. +** +** Return 1 on error, 2 to exit, and 0 otherwise. +*/ +static int do_meta_command(char *zLine, struct callback_data *p){ + int i = 1; + int nArg = 0; + int n, c; + int rc = 0; + char *azArg[50]; + + /* Parse the input line into tokens. + */ + while( zLine[i] && nArg1 && strncmp(azArg[0], "bail", n)==0 && nArg>1 ){ + bail_on_error = booleanValue(azArg[1]); + }else + + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 1; + data.mode = MODE_Column; + data.colWidth[0] = 3; + data.colWidth[1] = 15; + data.colWidth[2] = 58; + data.cnt = 0; + sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else + + if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ + char *zErrMsg = 0; + open_db(p); + fprintf(p->out, "BEGIN TRANSACTION;\n"); + p->writableSchema = 0; + if( nArg==1 ){ + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE sql NOT NULL AND type=='table'", 0 + ); + run_table_dump_query(p->out, p->db, + "SELECT sql FROM sqlite_master " + "WHERE sql NOT NULL AND type IN ('index','trigger','view')" + ); + }else{ + int i; + for(i=1; iout, p->db, + "SELECT sql FROM sqlite_master " + "WHERE sql NOT NULL" + " AND type IN ('index','trigger','view')" + " AND tbl_name LIKE shellstatic()" + ); + zShellStatic = 0; + } + } + if( p->writableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=OFF;\n"); + p->writableSchema = 0; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + }else{ + fprintf(p->out, "COMMIT;\n"); + } + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){ + p->echoOn = booleanValue(azArg[1]); + }else + + if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ + rc = 2; + }else + + if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ + int val = nArg>=2 ? booleanValue(azArg[1]) : 1; + if(val == 1) { + if(!p->explainPrev.valid) { + p->explainPrev.valid = 1; + p->explainPrev.mode = p->mode; + p->explainPrev.showHeader = p->showHeader; + memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); + } + /* We could put this code under the !p->explainValid + ** condition so that it does not execute if we are already in + ** explain mode. However, always executing it allows us an easy + ** was to reset to explain mode in case the user previously + ** did an .explain followed by a .width, .mode or .header + ** command. + */ + p->mode = MODE_Explain; + p->showHeader = 1; + memset(p->colWidth,0,ArraySize(p->colWidth)); + p->colWidth[0] = 4; /* addr */ + p->colWidth[1] = 13; /* opcode */ + p->colWidth[2] = 4; /* P1 */ + p->colWidth[3] = 4; /* P2 */ + p->colWidth[4] = 4; /* P3 */ + p->colWidth[5] = 13; /* P4 */ + p->colWidth[6] = 2; /* P5 */ + p->colWidth[7] = 13; /* Comment */ + }else if (p->explainPrev.valid) { + p->explainPrev.valid = 0; + p->mode = p->explainPrev.mode; + p->showHeader = p->explainPrev.showHeader; + memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); + } + }else + + if( c=='h' && (strncmp(azArg[0], "header", n)==0 || + strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){ + p->showHeader = booleanValue(azArg[1]); + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ + fprintf(stderr,zHelp); + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg>=3 ){ + char *zTable = azArg[2]; /* Insert data into this table */ + char *zFile = azArg[1]; /* The file from which to extract data */ + sqlite3_stmt *pStmt; /* A statement */ + int rc; /* Result code */ + int nCol; /* Number of columns in the table */ + int nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int nSep; /* Number of bytes in p->separator[] */ + char *zSql; /* An SQL statement */ + char *zLine; /* A single line of input from the file */ + char **azCol; /* zLine[] broken up into columns */ + char *zCommit; /* How to commit changes */ + FILE *in; /* The input file */ + int lineno = 0; /* Line number of input file */ + + open_db(p); + nSep = strlen(p->separator); + if( nSep==0 ){ + fprintf(stderr, "non-null separator required for import\n"); + return 0; + } + zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable); + if( zSql==0 ) return 0; + nByte = strlen(zSql); + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); + nCol = 0; + rc = 1; + }else{ + nCol = sqlite3_column_count(pStmt); + } + sqlite3_finalize(pStmt); + if( nCol==0 ) return 0; + zSql = malloc( nByte + 20 + nCol*2 ); + if( zSql==0 ) return 0; + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO '%q' VALUES(?", zTable); + j = strlen(zSql); + for(i=1; idb, zSql, -1, &pStmt, 0); + free(zSql); + if( rc ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); + sqlite3_finalize(pStmt); + return 1; + } + in = fopen(zFile, "rb"); + if( in==0 ){ + fprintf(stderr, "cannot open file: %s\n", zFile); + sqlite3_finalize(pStmt); + return 0; + } + azCol = malloc( sizeof(azCol[0])*(nCol+1) ); + if( azCol==0 ){ + fclose(in); + return 0; + } + sqlite3_exec(p->db, "BEGIN", 0, 0, 0); + zCommit = "COMMIT"; + while( (zLine = local_getline(0, in))!=0 ){ + char *z; + i = 0; + lineno++; + azCol[0] = zLine; + for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){ + if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){ + *z = 0; + i++; + if( idb, zCommit, 0, 0, 0); + }else + + if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_List; + zShellStatic = azArg[1]; + sqlite3_exec(p->db, + "SELECT name FROM sqlite_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "ORDER BY 1", + callback, &data, &zErrMsg + ); + zShellStatic = 0; + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else + +#ifdef SQLITE_ENABLE_IOTRACE + if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ + extern void (*sqlite3_io_trace)(const char*, ...); + if( iotrace && iotrace!=stdout ) fclose(iotrace); + iotrace = 0; + if( nArg<2 ){ + sqlite3_io_trace = 0; + }else if( strcmp(azArg[1], "-")==0 ){ + sqlite3_io_trace = iotracePrintf; + iotrace = stdout; + }else{ + iotrace = fopen(azArg[1], "w"); + if( iotrace==0 ){ + fprintf(stderr, "cannot open \"%s\"\n", azArg[1]); + sqlite3_io_trace = 0; + }else{ + sqlite3_io_trace = iotracePrintf; + } + } + }else +#endif + +#ifndef SQLITE_OMIT_LOAD_EXTENSION + if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ + const char *zFile, *zProc; + char *zErrMsg = 0; + int rc; + zFile = azArg[1]; + zProc = nArg>=3 ? azArg[2] : 0; + open_db(p); + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "%s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else +#endif + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ + int n2 = strlen(azArg[1]); + if( strncmp(azArg[1],"line",n2)==0 + || + strncmp(azArg[1],"lines",n2)==0 ){ + p->mode = MODE_Line; + }else if( strncmp(azArg[1],"column",n2)==0 + || + strncmp(azArg[1],"columns",n2)==0 ){ + p->mode = MODE_Column; + }else if( strncmp(azArg[1],"list",n2)==0 ){ + p->mode = MODE_List; + }else if( strncmp(azArg[1],"html",n2)==0 ){ + p->mode = MODE_Html; + }else if( strncmp(azArg[1],"tcl",n2)==0 ){ + p->mode = MODE_Tcl; + }else if( strncmp(azArg[1],"csv",n2)==0 ){ + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->separator), p->separator, ","); + }else if( strncmp(azArg[1],"tabs",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); + }else if( strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + if( nArg>=3 ){ + set_table_name(p, azArg[2]); + }else{ + set_table_name(p, "table"); + } + }else { + fprintf(stderr,"mode should be one of: " + "column csv html insert line list tabs tcl\n"); + } + }else + + if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { + sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, + "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); + }else + + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ + if( p->out!=stdout ){ + fclose(p->out); + } + if( strcmp(azArg[1],"stdout")==0 ){ + p->out = stdout; + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout"); + }else{ + p->out = fopen(azArg[1], "wb"); + if( p->out==0 ){ + fprintf(stderr,"can't write to \"%s\"\n", azArg[1]); + p->out = stdout; + } else { + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); + } + } + }else + + if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ + if( nArg >= 2) { + strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + } + if( nArg >= 3) { + strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + } + }else + + if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ + rc = 2; + }else + + if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ + FILE *alt = fopen(azArg[1], "rb"); + if( alt==0 ){ + fprintf(stderr,"can't open \"%s\"\n", azArg[1]); + }else{ + process_input(p, alt); + fclose(alt); + } + }else + + if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_Semi; + if( nArg>1 ){ + int i; + for(i=0; azArg[1][i]; i++) azArg[1][i] = tolower(azArg[1][i]); + if( strcmp(azArg[1],"sqlite_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TABLE sqlite_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + }else{ + zShellStatic = azArg[1]; + sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT * FROM sqlite_master UNION ALL" + " SELECT * FROM sqlite_temp_master) " + "WHERE tbl_name LIKE shellstatic() AND type!='meta' AND sql NOTNULL " + "ORDER BY substr(type,2,1), name", + callback, &data, &zErrMsg); + zShellStatic = 0; + } + }else{ + sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT * FROM sqlite_master UNION ALL" + " SELECT * FROM sqlite_temp_master) " + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" + "ORDER BY substr(type,2,1), name", + callback, &data, &zErrMsg + ); + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + }else + + if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ + sqlite3_snprintf(sizeof(p->separator), p->separator, + "%.*s", (int)sizeof(p->separator)-1, azArg[1]); + }else + + if( c=='s' && strncmp(azArg[0], "show", n)==0){ + int i; + fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); + fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); + fprintf(p->out,"%9.9s: ", "nullvalue"); + output_c_string(p->out, p->nullvalue); + fprintf(p->out, "\n"); + fprintf(p->out,"%9.9s: %s\n","output", + strlen(p->outfile) ? p->outfile : "stdout"); + fprintf(p->out,"%9.9s: ", "separator"); + output_c_string(p->out, p->separator); + fprintf(p->out, "\n"); + fprintf(p->out,"%9.9s: ","width"); + for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { + fprintf(p->out,"%d ",p->colWidth[i]); + } + fprintf(p->out,"\n"); + }else + + if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ + char **azResult; + int nRow, rc; + char *zErrMsg; + open_db(p); + if( nArg==1 ){ + rc = sqlite3_get_table(p->db, + "SELECT name FROM sqlite_master " + "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type IN ('table','view') " + "ORDER BY 1", + &azResult, &nRow, 0, &zErrMsg + ); + }else{ + zShellStatic = azArg[1]; + rc = sqlite3_get_table(p->db, + "SELECT name FROM sqlite_master " + "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type IN ('table','view') AND name LIKE '%'||shellstatic()||'%' " + "ORDER BY 1", + &azResult, &nRow, 0, &zErrMsg + ); + zShellStatic = 0; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + } + if( rc==SQLITE_OK ){ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=1; i<=nRow; i++){ + if( azResult[i]==0 ) continue; + len = strlen(azResult[i]); + if( len>maxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; i4 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ + open_db(p); + sqlite3_busy_timeout(p->db, atoi(azArg[1])); + }else + +#if HAS_TIMER + if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 && nArg>1 ){ + enableTimer = booleanValue(azArg[1]); + }else +#endif + + if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ + int j; + assert( nArg<=ArraySize(azArg) ); + for(j=1; jcolWidth); j++){ + p->colWidth[j-1] = atoi(azArg[j]); + } + }else + + + { + fprintf(stderr, "unknown command or invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[0]); + } + + return rc; +} + +/* +** Return TRUE if a semicolon occurs anywhere in the first N characters +** of string z[]. +*/ +static int _contains_semicolon(const char *z, int N){ + int i; + for(i=0; iout); + free(zLine); + zLine = one_input_line(zSql, in); + if( zLine==0 ){ + break; /* We have reached EOF */ + } + if( seenInterrupt ){ + if( in!=0 ) break; + seenInterrupt = 0; + } + lineno++; + if( p->echoOn ) printf("%s\n", zLine); + if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; + if( zLine && zLine[0]=='.' && nSql==0 ){ + rc = do_meta_command(zLine, p); + if( rc==2 ){ + break; + }else if( rc ){ + errCnt++; + } + continue; + } + if( _is_command_terminator(zLine) ){ + memcpy(zLine,";",2); + } + nSqlPrior = nSql; + if( zSql==0 ){ + int i; + for(i=0; zLine[i] && isspace((unsigned char)zLine[i]); i++){} + if( zLine[i]!=0 ){ + nSql = strlen(zLine); + zSql = malloc( nSql+1 ); + if( zSql==0 ){ + fprintf(stderr, "out of memory\n"); + exit(1); + } + memcpy(zSql, zLine, nSql+1); + startline = lineno; + } + }else{ + int len = strlen(zLine); + zSql = realloc( zSql, nSql + len + 2 ); + if( zSql==0 ){ + fprintf(stderr,"%s: out of memory!\n", Argv0); + exit(1); + } + zSql[nSql++] = '\n'; + memcpy(&zSql[nSql], zLine, len+1); + nSql += len; + } + if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) + && sqlite3_complete(zSql) ){ + p->cnt = 0; + open_db(p); + BEGIN_TIMER; + rc = sqlite3_exec(p->db, zSql, callback, p, &zErrMsg); + END_TIMER; + if( rc || zErrMsg ){ + char zPrefix[100]; + if( in!=0 || !stdin_is_interactive ){ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, + "SQL error near line %d:", startline); + }else{ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "SQL error:"); + } + if( zErrMsg!=0 ){ + printf("%s %s\n", zPrefix, zErrMsg); + sqlite3_free(zErrMsg); + zErrMsg = 0; + }else{ + printf("%s %s\n", zPrefix, sqlite3_errmsg(p->db)); + } + errCnt++; + } + free(zSql); + zSql = 0; + nSql = 0; + } + } + if( zSql ){ + if( !_all_whitespace(zSql) ) printf("Incomplete SQL: %s\n", zSql); + free(zSql); + } + free(zLine); + return errCnt; +} + +/* +** Return a pathname which is the user's home directory. A +** 0 return indicates an error of some kind. Space to hold the +** resulting string is obtained from malloc(). The calling +** function should free the result. +*/ +static char *find_home_dir(void){ + char *home_dir = NULL; + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) + struct passwd *pwent; + uid_t uid = getuid(); + if( (pwent=getpwuid(uid)) != NULL) { + home_dir = pwent->pw_dir; + } +#endif + +#if defined(_WIN32_WCE) + /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() + */ + home_dir = strdup("/"); +#else + +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) + if (!home_dir) { + home_dir = getenv("USERPROFILE"); + } +#endif + + if (!home_dir) { + home_dir = getenv("HOME"); + } + +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) + if (!home_dir) { + char *zDrive, *zPath; + int n; + zDrive = getenv("HOMEDRIVE"); + zPath = getenv("HOMEPATH"); + if( zDrive && zPath ){ + n = strlen(zDrive) + strlen(zPath) + 1; + home_dir = malloc( n ); + if( home_dir==0 ) return 0; + sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); + return home_dir; + } + home_dir = "c:\\"; + } +#endif + +#endif /* !_WIN32_WCE */ + + if( home_dir ){ + int n = strlen(home_dir) + 1; + char *z = malloc( n ); + if( z ) memcpy(z, home_dir, n); + home_dir = z; + } + + return home_dir; +} + +/* +** Read input from the file given by sqliterc_override. Or if that +** parameter is NULL, take input from ~/.sqliterc +*/ +static void process_sqliterc( + struct callback_data *p, /* Configuration data */ + const char *sqliterc_override /* Name of config file. NULL to use default */ +){ + char *home_dir = NULL; + const char *sqliterc = sqliterc_override; + char *zBuf = 0; + FILE *in = NULL; + int nBuf; + + if (sqliterc == NULL) { + home_dir = find_home_dir(); + if( home_dir==0 ){ + fprintf(stderr,"%s: cannot locate your home directory!\n", Argv0); + return; + } + nBuf = strlen(home_dir) + 16; + zBuf = malloc( nBuf ); + if( zBuf==0 ){ + fprintf(stderr,"%s: out of memory!\n", Argv0); + exit(1); + } + sqlite3_snprintf(nBuf, zBuf,"%s/.sqliterc",home_dir); + free(home_dir); + sqliterc = (const char*)zBuf; + } + in = fopen(sqliterc,"rb"); + if( in ){ + if( stdin_is_interactive ){ + printf("-- Loading resources from %s\n",sqliterc); + } + process_input(p,in); + fclose(in); + } + free(zBuf); + return; +} + +/* +** Show available command line options +*/ +static const char zOptions[] = + " -init filename read/process named file\n" + " -echo print commands before execution\n" + " -[no]header turn headers on or off\n" + " -bail stop after hitting an error\n" + " -interactive force interactive I/O\n" + " -batch force batch I/O\n" + " -column set output mode to 'column'\n" + " -csv set output mode to 'csv'\n" + " -html set output mode to HTML\n" + " -line set output mode to 'line'\n" + " -list set output mode to 'list'\n" + " -separator 'x' set output field separator (|)\n" + " -nullvalue 'text' set text string for NULL values\n" + " -version show SQLite version\n" +; +static void usage(int showDetail){ + fprintf(stderr, + "Usage: %s [OPTIONS] FILENAME [SQL]\n" + "FILENAME is the name of an SQLite database. A new database is created\n" + "if the file does not previously exist.\n", Argv0); + if( showDetail ){ + fprintf(stderr, "OPTIONS include:\n%s", zOptions); + }else{ + fprintf(stderr, "Use the -help option for additional information\n"); + } + exit(1); +} + +/* +** Initialize the state information in data +*/ +static void main_init(struct callback_data *data) { + memset(data, 0, sizeof(*data)); + data->mode = MODE_List; + memcpy(data->separator,"|", 2); + data->showHeader = 0; + sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); + sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); +} + +int main(int argc, char **argv){ + char *zErrMsg = 0; + struct callback_data data; + const char *zInitFile = 0; + char *zFirstCmd = 0; + int i; + int rc = 0; + + Argv0 = argv[0]; + main_init(&data); + stdin_is_interactive = isatty(0); + + /* Make sure we have a valid signal handler early, before anything + ** else is done. + */ +#ifdef SIGINT + signal(SIGINT, interrupt_handler); +#endif + + /* Do an initial pass through the command-line argument to locate + ** the name of the database file, the name of the initialization file, + ** and the first command to execute. + */ + for(i=1; i /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + + +/* +** Add the ability to override 'extern' +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif + +/* +** Make sure these symbols where not defined by some previous header +** file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers {F10010} +** +** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in +** the sqlite3.h file specify the version of SQLite with which +** that header file is associated. +** +** The "version" of SQLite is a strong of the form "X.Y.Z". +** The phrase "alpha" or "beta" might be appended after the Z. +** The X value is major version number always 3 in SQLite3. +** The X value only changes when backwards compatibility is +** broken and we intend to never break +** backwards compatibility. The Y value is the minor version +** number and only changes when +** there are major feature enhancements that are forwards compatible +** but not backwards compatible. The Z value is release number +** and is incremented with +** each release but resets back to 0 when Y is incremented. +** +** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. +** +** INVARIANTS: +** +** {F10011} The SQLITE_VERSION #define in the sqlite3.h header file +** evaluates to a string literal that is the SQLite version +** with which the header file is associated. +** +** {F10014} The SQLITE_VERSION_NUMBER #define resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and +** Z are the major version, minor version, and release number. +*/ +#define SQLITE_VERSION "--VERS--" +#define SQLITE_VERSION_NUMBER --VERSION-NUMBER-- + +/* +** CAPI3REF: Run-Time Library Version Numbers {F10020} +** KEYWORDS: sqlite3_version +** +** These features provide the same information as the [SQLITE_VERSION] +** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated +** with the library instead of the header file. Cautious programmers might +** include a check in their application to verify that +** sqlite3_libversion_number() always returns the value +** [SQLITE_VERSION_NUMBER]. +** +** The sqlite3_libversion() function returns the same information as is +** in the sqlite3_version[] string constant. The function is provided +** for use in DLLs since DLL users usually do not have direct access to string +** constants within the DLL. +** +** INVARIANTS: +** +** {F10021} The [sqlite3_libversion_number()] interface returns an integer +** equal to [SQLITE_VERSION_NUMBER]. +** +** {F10022} The [sqlite3_version] string constant contains the text of the +** [SQLITE_VERSION] string. +** +** {F10023} The [sqlite3_libversion()] function returns +** a pointer to the [sqlite3_version] string constant. +*/ +SQLITE_EXTERN const char sqlite3_version[]; +const char *sqlite3_libversion(void); +int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe {F10100} +** +** SQLite can be compiled with or without mutexes. When +** the SQLITE_THREADSAFE C preprocessor macro is true, mutexes +** are enabled and SQLite is threadsafe. When that macro os false, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite from more than one thread. +** +** There is a measurable performance penalty for enabling mutexes. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** The default behavior is for mutexes to be enabled. +** +** This interface can be used by a program to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the SQLITE_THREADSAFE macro. +** +** INVARIANTS: +** +** {F10101} The [sqlite3_threadsafe()] function returns nonzero if +** SQLite was compiled with its mutexes enabled or zero +** if SQLite was compiled with mutexes disabled. +*/ +int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle {F12000} +** KEYWORDS: {database connection} +** +** Each open SQLite database is represented by pointer to an instance of the +** opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors +** and [sqlite3_close()] is its destructor. There are many other interfaces +** (such as [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on this +** object. +*/ +typedef struct sqlite3 sqlite3; + + +/* +** CAPI3REF: 64-Bit Integer Types {F10200} +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type +** definitions. The sqlite_int64 and sqlite_uint64 types are +** supported for backwards compatibility only. +** +** INVARIANTS: +** +** {F10201} The [sqlite_int64] and [sqlite3_int64] types specify a +** 64-bit signed integer. +** +** {F10202} The [sqlite_uint64] and [sqlite3_uint64] types specify +** a 64-bit unsigned integer. +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection {F12010} +** +** This routine is the destructor for the [sqlite3] object. +** +** Applications should [sqlite3_finalize | finalize] all +** [prepared statements] and +** [sqlite3_blob_close | close] all [sqlite3_blob | BLOBs] +** associated with the [sqlite3] object prior +** to attempting to close the [sqlite3] object. +** +** What happens to pending transactions? Are they +** rolled back, or abandoned? +** +** INVARIANTS: +** +** {F12011} The [sqlite3_close()] interface destroys an [sqlite3] object +** allocated by a prior call to [sqlite3_open()], +** [sqlite3_open16()], or [sqlite3_open_v2()]. +** +** {F12012} The [sqlite3_close()] function releases all memory used by the +** connection and closes all open files. +** +** {F12013} If the database connection contains +** [prepared statements] that have not been +** finalized by [sqlite3_finalize()], then [sqlite3_close()] +** returns [SQLITE_BUSY] and leaves the connection open. +** +** {F12014} Giving sqlite3_close() a NULL pointer is a harmless no-op. +** +** LIMITATIONS: +** +** {U12015} The parameter to [sqlite3_close()] must be an [sqlite3] object +** pointer previously obtained from [sqlite3_open()] or the +** equivalent, or NULL. +** +** {U12016} The parameter to [sqlite3_close()] must not have been previously +** closed. +*/ +int sqlite3_close(sqlite3 *); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface {F12100} +** +** The sqlite3_exec() interface is a convenient way of running +** one or more SQL statements without a lot of C code. The +** SQL statements are passed in as the second parameter to +** sqlite3_exec(). The statements are evaluated one by one +** until either an error or an interrupt is encountered or +** until they are all done. The 3rd parameter is an optional +** callback that is invoked once for each row of any query results +** produced by the SQL statements. The 5th parameter tells where +** to write any error messages. +** +** The sqlite3_exec() interface is implemented in terms of +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()]. +** The sqlite3_exec() routine does nothing that cannot be done +** by [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()]. +** The sqlite3_exec() is just a convenient wrapper. +** +** INVARIANTS: +** +** {F12101} The [sqlite3_exec()] interface evaluates zero or more UTF-8 +** encoded, semicolon-separated, SQL statements in the +** zero-terminated string of its 2nd parameter within the +** context of the [sqlite3] object given in the 1st parameter. +** +** {F12104} The return value of [sqlite3_exec()] is SQLITE_OK if all +** SQL statements run successfully. +** +** {F12105} The return value of [sqlite3_exec()] is an appropriate +** non-zero error code if any SQL statement fails. +** +** {F12107} If one or more of the SQL statements handed to [sqlite3_exec()] +** return results and the 3rd parameter is not NULL, then +** the callback function specified by the 3rd parameter is +** invoked once for each row of result. +** +** {F12110} If the callback returns a non-zero value then [sqlite3_exec()] +** will aborted the SQL statement it is currently evaluating, +** skip all subsequent SQL statements, and return [SQLITE_ABORT]. +** What happens to *errmsg here? Does the result code for +** sqlite3_errcode() get set? +** +** {F12113} The [sqlite3_exec()] routine will pass its 4th parameter through +** as the 1st parameter of the callback. +** +** {F12116} The [sqlite3_exec()] routine sets the 2nd parameter of its +** callback to be the number of columns in the current row of +** result. +** +** {F12119} The [sqlite3_exec()] routine sets the 3rd parameter of its +** callback to be an array of pointers to strings holding the +** values for each column in the current result set row as +** obtained from [sqlite3_column_text()]. +** +** {F12122} The [sqlite3_exec()] routine sets the 4th parameter of its +** callback to be an array of pointers to strings holding the +** names of result columns as obtained from [sqlite3_column_name()]. +** +** {F12125} If the 3rd parameter to [sqlite3_exec()] is NULL then +** [sqlite3_exec()] never invokes a callback. All query +** results are silently discarded. +** +** {F12128} If an error occurs while parsing or evaluating any of the SQL +** statements handed to [sqlite3_exec()] then [sqlite3_exec()] will +** return an [error code] other than [SQLITE_OK]. +** +** {F12131} If an error occurs while parsing or evaluating any of the SQL +** handed to [sqlite3_exec()] and if the 5th parameter (errmsg) +** to [sqlite3_exec()] is not NULL, then an error message is +** allocated using the equivalent of [sqlite3_mprintf()] and +** *errmsg is made to point to that message. +** +** {F12134} The [sqlite3_exec()] routine does not change the value of +** *errmsg if errmsg is NULL or if there are no errors. +** +** {F12137} The [sqlite3_exec()] function sets the error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** +** LIMITATIONS: +** +** {U12141} The first parameter to [sqlite3_exec()] must be an valid and open +** [database connection]. +** +** {U12142} The database connection must not be closed while +** [sqlite3_exec()] is running. +** +** {U12143} The calling function is should use [sqlite3_free()] to free +** the memory that *errmsg is left pointing at once the error +** message is no longer needed. +** +** {U12145} The SQL statement text in the 2nd parameter to [sqlite3_exec()] +** must remain unchanged while [sqlite3_exec()] is running. +*/ +int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluted */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes {F10210} +** KEYWORDS: SQLITE_OK {error code} {error codes} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicates success or failure. +** +** See also: [SQLITE_IOERR_READ | extended result codes] +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes {F10220} +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result codes} +** +** In its default configuration, SQLite API routines return one of 26 integer +** [SQLITE_OK | result codes]. However, experience has shown that +** many of these result codes are too course-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. The extended result codes are enabled or disabled +** for each database connection using the [sqlite3_extended_result_codes()] +** API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +** +** INVARIANTS: +** +** {F10223} The symbolic name for an extended result code always contains +** a related primary result code as a prefix. +** +** {F10224} Primary result code names contain a single "_" character. +** +** {F10225} Extended result code names contain two or more "_" characters. +** +** {F10226} The numeric value of an extended result code contains the +** numeric value of its corresponding primary result code it +** its least significant 8 bits. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) + +/* +** CAPI3REF: Flags For File Open Operations {F10230} +** +** These bit values are intended for use in then +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the xOpen method of the +** [sqlite3_vfs] object. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 +#define SQLITE_OPEN_READWRITE 0x00000002 +#define SQLITE_OPEN_CREATE 0x00000004 +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 +#define SQLITE_OPEN_MAIN_DB 0x00000100 +#define SQLITE_OPEN_TEMP_DB 0x00000200 +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 + +/* +** CAPI3REF: Device Characteristics {F10240} +** +** The xDeviceCapabilities method of the [sqlite3_io_methods] +** object returns an integer which is a vector of the these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 + +/* +** CAPI3REF: File Locking Levels {F10250} +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags {F10260} +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of the +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. The SQLITE_SYNC_NORMAL means +** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means +** to use Mac OS-X style fullsync instead of fsync(). +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + + +/* +** CAPI3REF: OS Interface Open File Handle {F11110} +** +** An [sqlite3_file] object represents an open file in the OS +** interface layer. Individual OS interface implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file { + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object {F11120} +** +** Every file opened by the [sqlite3_vfs] xOpen method contains a pointer to +** an instance of the this object. This object defines the +** methods used to perform various operations against the open file. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +* The second choice is an +** OS-X style fullsync. The SQLITE_SYNC_DATA flag may be ORed in to +** indicate that only the data of the file and not its inode needs to be +** synced. +** +** The integer values to xLock() and xUnlock() are one of +**
    +**
  • [SQLITE_LOCK_NONE], +**
  • [SQLITE_LOCK_SHARED], +**
  • [SQLITE_LOCK_RESERVED], +**
  • [SQLITE_LOCK_PENDING], or +**
  • [SQLITE_LOCK_EXCLUSIVE]. +**
+** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method looks +** to see if any database connection, either in this +** process or in some other process, is holding an RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false if not. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument +** is an integer opcode. The third +** argument is a generic pointer which is intended to be a pointer +** to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves opcodes less than 100 for its own use. +** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
    +**
  • [SQLITE_IOCAP_ATOMIC] +**
  • [SQLITE_IOCAP_ATOMIC512] +**
  • [SQLITE_IOCAP_ATOMIC1K] +**
  • [SQLITE_IOCAP_ATOMIC2K] +**
  • [SQLITE_IOCAP_ATOMIC4K] +**
  • [SQLITE_IOCAP_ATOMIC8K] +**
  • [SQLITE_IOCAP_ATOMIC16K] +**
  • [SQLITE_IOCAP_ATOMIC32K] +**
  • [SQLITE_IOCAP_ATOMIC64K] +**
  • [SQLITE_IOCAP_SAFE_APPEND] +**
  • [SQLITE_IOCAP_SEQUENTIAL] +**
+** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods { + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes {F11310} +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and to the [sqlite3_file_control()] +** interface. +** +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode cases 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. +*/ +#define SQLITE_FCNTL_LOCKSTATE 1 + +/* +** CAPI3REF: Mutex Handle {F17110} +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: OS Interface Object {F11140} +** +** An instance of this object defines the interface between the +** SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". +** +** The iVersion field is initially 1 but may be larger for future +** versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered vfs modules are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. +** +** The pNext field is the only fields in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** {F11141} SQLite will guarantee that the zFilename string passed to +** xOpen() is a full pathname as generated by xFullPathname() and +** that the string will be valid and unchanged until xClose() is +** called. {END} So the [sqlite3_file] can store a pointer to the +** filename if it needs to remember the filename for some reason. +** +** {F11142} The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END} +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be +** set. +** +** {F11143} SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
    +**
  • [SQLITE_OPEN_MAIN_DB] +**
  • [SQLITE_OPEN_MAIN_JOURNAL] +**
  • [SQLITE_OPEN_TEMP_DB] +**
  • [SQLITE_OPEN_TEMP_JOURNAL] +**
  • [SQLITE_OPEN_TRANSIENT_DB] +**
  • [SQLITE_OPEN_SUBJOURNAL] +**
  • [SQLITE_OPEN_MASTER_JOURNAL] +**
{END} +** +** The file I/O implementation can use the object type flags to +** changes the way it deals with files. For example, an application +** that does not care about crash recovery or rollback, might make +** the open of a journal file a no-op. Writes to this journal are +** also a no-op. Any attempt to read the journal return SQLITE_IOERR. +** Or the implementation might recognize the a database file will +** be doing page-aligned sector reads and writes in a random order +** and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen +** method: +** +**
    +**
  • [SQLITE_OPEN_DELETEONCLOSE] +**
  • [SQLITE_OPEN_EXCLUSIVE] +**
+** +** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases, journals and for subjournals. +** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened +** for exclusive access. This flag is set for all files except +** for the main database file. {END} +** +** {F11148} At least szOsFile bytes of memory is allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. {END} The xOpen method does not have to +** allocate the structure; it should just fill it in. +** +** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existance of a file, +** or [SQLITE_ACCESS_READWRITE] to test to see +** if a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test to see if a file is at least readable. {END} The file can be a +** directory. +** +** {F11150} SQLite will always allocate at least mxPathname+1 byte for +** the output buffers for xGetTempname and xFullPathname. {F11151} The exact +** size of the output buffer is also passed as a parameter to both +** methods. {END} If the output buffer is not large enough, SQLITE_CANTOPEN +** should be returned. As this is handled as a fatal error by SQLite, +** vfs implementations should endeavor to prevent this by setting +** mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), and xCurrentTime() interfaces +** are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. The +** xSleep() method cause the calling thread to sleep for at +** least the number of microseconds given. The xCurrentTime() +** method returns a Julian Day Number for the current date and +** time. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +struct sqlite3_vfs { + int iVersion; /* Structure version number */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags); + int (*xGetTempname)(sqlite3_vfs*, int nOut, char *zOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + /* New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method {F11190} +** +** {F11191} These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. {END} They determine +** the kind of what kind of permissions the xAccess method is +** looking for. {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks to see if the file exists. {F11193} With +** SQLITE_ACCESS_READWRITE, the xAccess method checks to see +** if the file is both readable and writable. {F11194} With +** SQLITE_ACCESS_READ the xAccess method +** checks to see if the file is readable. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 +#define SQLITE_ACCESS_READ 2 + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes {F12200} +** +** The sqlite3_extended_result_codes() routine enables or disables the +** [SQLITE_IOERR_READ | extended result codes] feature of SQLite. +** The extended result codes are disabled by default for historical +** compatibility. +** +** INVARIANTS: +** +** {F12201} Each new [database connection] has the +** [extended result codes] feature +** disabled by default. +** +** {F12202} The [sqlite3_extended_result_codes(D,F)] interface will enable +** [extended result codes] for the +** [database connection] D if the F parameter +** is true, or disable them if F is false. +*/ +int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid {F12220} +** +** Each entry in an SQLite table has a unique 64-bit signed +** integer key called the "rowid". The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. If +** the table has a column of type INTEGER PRIMARY KEY then that column +** is another an alias for the rowid. +** +** This routine returns the rowid of the most recent +** successful INSERT into the database from the database connection +** shown in the first argument. If no successful inserts +** have ever occurred on this database connection, zero is returned. +** +** If an INSERT occurs within a trigger, then the rowid of the +** inserted row is returned by this routine as long as the trigger +** is running. But once the trigger terminates, the value returned +** by this routine reverts to the last value inserted before the +** trigger fired. +** +** An INSERT that fails due to a constraint violation is not a +** successful insert and does not change the value returned by this +** routine. Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface. +** +** For the purposes of this routine, an insert is considered to +** be successful even if it is subsequently rolled back. +** +** INVARIANTS: +** +** {F12221} The [sqlite3_last_insert_rowid()] function returns the +** rowid of the most recent successful insert done +** on the same database connection and within the same +** trigger context, or zero if there have +** been no qualifying inserts on that connection. +** +** {F12223} The [sqlite3_last_insert_rowid()] function returns +** same value when called from the same trigger context +** immediately before and after a ROLLBACK. +** +** LIMITATIONS: +** +** {U12232} If separate thread does a new insert on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert rowid, +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert rowid. +*/ +sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified {F12240} +** +** This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the connection specified by the first parameter. Only +** changes that are directly specified by the INSERT, UPDATE, or +** DELETE statement are counted. Auxiliary changes caused by +** triggers are not counted. Use the [sqlite3_total_changes()] function +** to find the total number of changes including changes caused by triggers. +** +** A "row changes" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of REPLACE constraint resolution, +** rollback, ABORT processing, DROP TABLE, or by any other +** mechanisms do not count as direct row changes. +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a trigger. Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** So when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. +** Within the body of a trigger, the sqlite3_changes() interface +** can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the same trigger. +** However, the number returned does not include in changes +** caused by subtriggers since they have their own context. +** +** SQLite implements the command "DELETE FROM table" without +** a WHERE clause by dropping and recreating the table. (This is much +** faster than going through and deleting individual elements from the +** table.) Because of this optimization, the deletions in +** "DELETE FROM table" are not row changes and will not be counted +** by the sqlite3_changes() or [sqlite3_total_changes()] functions. +** To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +** +** INVARIANTS: +** +** {F12241} The [sqlite3_changes()] function returns the number of +** row changes caused by the most recent INSERT, UPDATE, +** or DELETE statement on the same database connection and +** within the same trigger context, or zero if there have +** not been any qualifying row changes. +** +** LIMITATIONS: +** +** {U12252} If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and unmeaningful. +*/ +int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified {F12260} +*** +** This function returns the number of row changes caused +** by INSERT, UPDATE or DELETE statements since the database handle +** was opened. The count includes all changes from all trigger +** contexts. But the count does not include changes used to +** implement REPLACE constraints, do rollbacks or ABORT processing, +** or DROP table processing. +** The changes +** are counted as soon as the statement that makes them is completed +** (when the statement handle is passed to [sqlite3_reset()] or +** [sqlite3_finalize()]). +** +** SQLite implements the command "DELETE FROM table" without +** a WHERE clause by dropping and recreating the table. (This is much +** faster than going +** through and deleting individual elements form the table.) Because of +** this optimization, the change count for "DELETE FROM table" will be +** zero regardless of the number of elements that were originally in the +** table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +** +** See also the [sqlite3_changes()] interface. +** +** INVARIANTS: +** +** {F12261} The [sqlite3_total_changes()] returns the total number +** of row changes caused by INSERT, UPDATE, and/or DELETE +** statements on the same [database connection], in any +** trigger context, since the database connection was +** created. +** +** LIMITATIONS: +** +** {U12264} If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and unmeaningful. +*/ +int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query {F12270} +** +** This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a database connection that +** is closed or might close before sqlite3_interrupt() returns. +** +** If an SQL is very nearly finished at the time when sqlite3_interrupt() +** is called, then it might not have an opportunity to be interrupted. +** It might continue to completion. +** An SQL operation that is interrupted will return +** [SQLITE_INTERRUPT]. If the interrupted SQL operation is an +** INSERT, UPDATE, or DELETE that is inside an explicit transaction, +** then the entire transaction will be rolled back automatically. +** A call to sqlite3_interrupt() has no effect on SQL statements +** that are started after sqlite3_interrupt() returns. +** +** INVARIANTS: +** +** {F12271} The [sqlite3_interrupt()] interface will force all running +** SQL statements associated with the same database connection +** to halt after processing at most one additional row of +** data. +** +** {F12272} Any SQL statement that is interrupted by [sqlite3_interrupt()] +** will return [SQLITE_INTERRUPT]. +** +** LIMITATIONS: +** +** {U12279} If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete {F10510} +** +** These routines are useful for command-line input to determine if the +** currently entered text seems to form complete a SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. These routines return true if the input string +** appears to be a complete SQL statement. A statement is judged to be +** complete if it ends with a semicolon token and is not a fragment of a +** CREATE TRIGGER statement. Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. +** +** These routines do not parse the SQL and +** so will not detect syntactically incorrect SQL. +** +** INVARIANTS: +** +** {F10511} The sqlite3_complete() and sqlite3_complete16() functions +** return true (non-zero) if and only if the last +** non-whitespace token in their input is a semicolon that +** is not in between the BEGIN and END of a CREATE TRIGGER +** statement. +** +** LIMITATIONS: +** +** {U10512} The input to sqlite3_complete() must be a zero-terminated +** UTF-8 string. +** +** {U10513} The input to sqlite3_complete16() must be a zero-terminated +** UTF-16 string in native byte order. +*/ +int sqlite3_complete(const char *sql); +int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310} +** +** This routine identifies a callback function that might be +** invoked whenever an attempt is made to open a database table +** that another thread or process has locked. +** If the busy callback is NULL, then [SQLITE_BUSY] +** or [SQLITE_IOERR_BLOCKED] +** is returned immediately upon encountering the lock. +** If the busy callback is not NULL, then the +** callback will be invoked with two arguments. The +** first argument to the handler is a copy of the void* pointer which +** is the third argument to this routine. The second argument to +** the handler is the number of times that the busy handler has +** been invoked for this locking event. If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. +** If the callback returns non-zero, then another attempt +** is made to open the database for reading and the cycle repeats. +** +** The presence of a busy handler does not guarantee that +** it will be invoked when there is lock contention. +** If SQLite determines that invoking the busy handler could result in +** a deadlock, it will go ahead and return [SQLITE_BUSY] or +** [SQLITE_IOERR_BLOCKED] instead of invoking the +** busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** The default busy callback is NULL. +** +** The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] +** when SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** There can only be a single busy handler defined for each database +** connection. Setting a new busy handler clears any previous one. +** Note that calling [sqlite3_busy_timeout()] will also set or clear +** the busy handler. +** +** INVARIANTS: +** +** {F12311} The [sqlite3_busy_handler()] function replaces the busy handler +** callback in the database connection identified by the 1st +** parameter with a new busy handler identified by the 2nd and 3rd +** parameters. +** +** {F12312} The default busy handler for new database connections is NULL. +** +** {F12314} When two or more database connection share a common cache, +** the busy handler for the database connection currently using +** the cache is invoked when the cache encounters a lock. +** +** {F12316} If a busy handler callback returns zero, then the SQLite +** interface that provoked the locking event will return +** [SQLITE_BUSY]. +** +** {F12318} SQLite will invokes the busy handler with two argument which +** are a copy of the pointer supplied by the 3rd parameter to +** [sqlite3_busy_handler()] and a count of the number of prior +** invocations of the busy handler for the same locking event. +** +** LIMITATIONS: +** +** {U12319} A busy handler should not call close the database connection +** or prepared statement that invoked the busy handler. +*/ +int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout {F12340} +** +** This routine sets a [sqlite3_busy_handler | busy handler] +** that sleeps for a while when a +** table is locked. The handler will sleep multiple times until +** at least "ms" milliseconds of sleeping have been done. {F12343} After +** "ms" milliseconds of sleeping, the handler returns 0 which +** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** There can only be a single busy handler for a particular database +** connection. If another busy handler was defined +** (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared. +** +** INVARIANTS: +** +** {F12341} The [sqlite3_busy_timeout()] function overrides any prior +** [sqlite3_busy_timeout()] or [sqlite3_busy_handler()] setting +** on the same database connection. +** +** {F12343} If the 2nd parameter to [sqlite3_busy_timeout()] is less than +** or equal to zero, then the busy handler is cleared so that +** all subsequent locking events immediately return [SQLITE_BUSY]. +** +** {F12344} If the 2nd parameter to [sqlite3_busy_timeout()] is a positive +** number N, then a busy handler is set that repeatedly calls +** the xSleep() method in the VFS interface until either the +** lock clears or until the cumulative sleep time reported back +** by xSleep() exceeds N milliseconds. +*/ +int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries {F12370} +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated +** UTF-8 strings. There are (N+1)*M elements in the array. +** The first M pointers point to zero-terminated strings that +** contain the names of the columns. +** The remaining entries all point to query results. NULL +** values are give a NULL pointer. All other values are in +** their UTF-8 zero-terminated string representation as returned by +** [sqlite3_column_text()]. +** +** A result table might consists of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** As an example of the result table format, suppose a query result +** is as follows: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
+** +** The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter. It returns a result table to the +** pointer given in its 3rd parameter. +** +** After the calling function has finished using the result, it should +** pass the pointer to the result table to sqlite3_free_table() in order to +** release the memory that was malloc-ed. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +** +** INVARIANTS: +** +** {F12371} If a [sqlite3_get_table()] fails a memory allocation, then +** it frees the result table under construction, aborts the +** query in process, skips any subsequent queries, sets the +** *resultp output pointer to NULL and returns [SQLITE_NOMEM]. +** +** {F12373} If the ncolumn parameter to [sqlite3_get_table()] is not NULL +** then [sqlite3_get_table()] write the number of columns in the +** result set of the query into *ncolumn if the query is +** successful (if the function returns SQLITE_OK). +** +** {F12374} If the nrow parameter to [sqlite3_get_table()] is not NULL +** then [sqlite3_get_table()] write the number of rows in the +** result set of the query into *nrow if the query is +** successful (if the function returns SQLITE_OK). +** +** {F12376} The [sqlite3_get_table()] function sets its *ncolumn value +** to the number of columns in the result set of the query in the +** sql parameter, or to zero if the query in sql has an empty +** result set. +*/ +int sqlite3_get_table( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + char ***pResult, /* Results of the query */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg /* Error msg written here */ +); +void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions {F17400} +** +** These routines are workalikes of the "printf()" family of functions +** from the standard C library. +** +** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** In sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf(). This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer. We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** 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. +** +** The %q option works like %s in that it substitutes a null-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal. By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, so some string variable contains text as follows: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** This second example is an SQL syntax error. As a general rule you +** should always use %q instead of %s when inserting text into a string +** literal. +** +** The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Or if the parameter in the argument +** list is a NULL pointer, %Q substitutes the text "NULL" (without single +** quotes) in place of the %Q option. {END} So, for example, one could say: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** The "%z" formatting option works exactly like "%s" with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string. {END} +** +** INVARIANTS: +** +** {F17403} The [sqlite3_mprintf()] and [sqlite3_vmprintf()] interfaces +** return either pointers to zero-terminated UTF-8 strings held in +** memory obtained from [sqlite3_malloc()] or NULL pointers if +** a call to [sqlite3_malloc()] fails. +** +** {F17406} The [sqlite3_snprintf()] interface writes a zero-terminated +** UTF-8 string into the buffer pointed to by the second parameter +** provided that the first parameter is greater than zero. +** +** {F17407} The [sqlite3_snprintf()] interface does not writes slots of +** its output buffer (the second parameter) outside the range +** of 0 through N-1 (where N is the first parameter) +** regardless of the length of the string +** requested by the format specification. +** +*/ +char *sqlite3_mprintf(const char*,...); +char *sqlite3_vmprintf(const char*, va_list); +char *sqlite3_snprintf(int,char*,const char*, ...); + +/* +** CAPI3REF: Memory Allocation Subsystem {F17300} +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** windows VFS uses native malloc and free for some operations. +** +** The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_free(). +** +** The sqlite3_realloc() interface attempts to resize a +** prior memory allocation to be at least N bytes, where N is the +** second parameter. The memory allocation to be resized is the first +** parameter. If the first parameter to sqlite3_realloc() +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). +** If the second parameter to sqlite3_realloc() is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). +** Sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. +** If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc() and the prior allocation is freed. +** If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. +** +** The memory returned by sqlite3_malloc() and sqlite3_realloc() +** is always aligned to at least an 8 byte boundary. {END} +** +** The default implementation +** of the memory allocation subsystem uses the malloc(), realloc() +** and free() provided by the standard C library. {F17382} However, if +** SQLite is compiled with the following C preprocessor macro +** +**
SQLITE_MEMORY_SIZE=NNN
+** +** where NNN is an integer, then SQLite create a static +** array of at least NNN bytes in size and use that array +** for all of its dynamic memory allocation needs. {END} Additional +** memory allocator options may be added in future releases. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be +** used. +** +** The windows OS interface layer calls +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular windows +** installation. Memory allocation errors are detected, but +** they are reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** INVARIANTS: +** +** {F17303} The [sqlite3_malloc(N)] interface returns either a pointer to +** newly checked-out block of at least N bytes of memory +** that is 8-byte aligned, +** or it returns NULL if it is unable to fulfill the request. +** +** {F17304} The [sqlite3_malloc(N)] interface returns a NULL pointer if +** N is less than or equal to zero. +** +** {F17305} The [sqlite3_free(P)] interface releases memory previously +** returned from [sqlite3_malloc()] or [sqlite3_realloc()], +** making it available for reuse. +** +** {F17306} A call to [sqlite3_free(NULL)] is a harmless no-op. +** +** {F17310} A call to [sqlite3_realloc(0,N)] is equivalent to a call +** to [sqlite3_malloc(N)]. +** +** {F17312} A call to [sqlite3_realloc(P,0)] is equivalent to a call +** to [sqlite3_free(P)]. +** +** {F17315} The SQLite core uses [sqlite3_malloc()], [sqlite3_realloc()], +** and [sqlite3_free()] for all of its memory allocation and +** deallocation needs. +** +** {F17318} The [sqlite3_realloc(P,N)] interface returns either a pointer +** to a block of checked-out memory of at least N bytes in size +** that is 8-byte aligned, or a NULL pointer. +** +** {F17321} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first +** copies the first K bytes of content from P into the newly allocated +** where K is the lessor of N and the size of the buffer P. +** +** {F17322} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first +** releases the buffer P. +** +** {F17323} When [sqlite3_realloc(P,N)] returns NULL, the buffer P is +** not modified or released. +** +** LIMITATIONS: +** +** {U17350} The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else a pointer obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that has +** not been released. +** +** {U17351} The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +** +*/ +void *sqlite3_malloc(int); +void *sqlite3_realloc(void*, int); +void sqlite3_free(void*); + +/* +** CAPI3REF: Memory Allocator Statistics {F17370} +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** the memory allocation subsystem included within the SQLite. +** +** INVARIANTS: +** +** {F17371} The [sqlite3_memory_used()] routine returns the +** number of bytes of memory currently outstanding +** (malloced but not freed). +** +** {F17373} The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] +** since the highwater mark was last reset. +** +** {F17374} The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** {F17375} The memory highwater mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. The value returned +** by [sqlite3_memory_highwater(1)] is the highwater mark +** prior to the reset. +*/ +sqlite3_int64 sqlite3_memory_used(void); +sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks {F12500} +** +** This routine registers a authorizer callback with a particular +** database connection, supplied in the first argument. +** The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. The authorizer callback should +** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. If the authorizer code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the prepared +** statement is constructed to insert a NULL value in place of +** the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** +** The first parameter to the authorizer callback is a copy of +** the third parameter to the sqlite3_set_authorizer() interface. +** The second parameter to the callback is an integer +** [SQLITE_COPY | action code] that specifies the particular action +** to be authorized. The third through sixth +** parameters to the callback are zero-terminated strings that contain +** additional details about the action to be authorized. +** +** An authorizer is used when preparing SQL statements from an untrusted +** source, to ensure that the SQL statements do not try to access data +** that they are not allowed to see, or that they do not try to +** execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being prepared that disallows everything +** except SELECT statements. +** +** Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call. Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()]. +** +** INVARIANTS: +** +** {F12501} The [sqlite3_set_authorizer(D,...)] interface registers a +** authorizer callback with database connection D. +** +** {F12502} The authorizer callback is invoked as SQL statements are +** being compiled +** +** {F12503} If the authorizer callback returns any value other than +** [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] then +** the [sqlite3_prepare_v2()] or equivalent call that caused +** the authorizer callback to run shall fail with an +** [SQLITE_ERROR] error code and an appropriate error message. +** +** {F12504} When the authorizer callback returns [SQLITE_OK], the operation +** described is coded normally. +** +** {F12505} When the authorizer callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that caused the +** authorizer callback to run shall fail +** with an [SQLITE_ERROR] error code and an error message +** explaining that access is denied. +** +** {F12506} If the authorizer code (the 2nd parameter to the authorizer +** callback) is [SQLITE_READ] and the authorizer callback returns +** [SQLITE_IGNORE] then the prepared statement is constructed to +** insert a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. +** +** {F12507} If the authorizer code (the 2nd parameter to the authorizer +** callback) is anything other than [SQLITE_READ], then +** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY]. +** +** {F12510} The first parameter to the authorizer callback is a copy of +** the third parameter to the [sqlite3_set_authorizer()] interface. +** +** {F12511} The second parameter to the callback is an integer +** [SQLITE_COPY | action code] that specifies the particular action +** to be authorized. +** +** {F12512} The third through sixth parameters to the callback are +** zero-terminated strings that contain +** additional details about the action to be authorized. +** +** {F12520} Each call to [sqlite3_set_authorizer()] overrides the +** any previously installed authorizer. +** +** {F12521} A NULL authorizer means that no authorization +** callback is invoked. +** +** {F12522} The default authorizer is NULL. +*/ +int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes {F12590} +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes {F12550} +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorizer certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable. The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +** +** INVARIANTS: +** +** {F12551} The second parameter to an +** [sqlite3_set_authorizer | authorizer callback is always an integer +** [SQLITE_COPY | authorizer code] that specifies what action +** is being authorized. +** +** {F12552} The 3rd and 4th parameters to the +** [sqlite3_set_authorizer | authorization callback function] +** will be parameters or NULL depending on which +** [SQLITE_COPY | authorizer code] is used as the second parameter. +** +** {F12553} The 5th parameter to the +** [sqlite3_set_authorizer | authorizer callback] is the name +** of the database (example: "main", "temp", etc.) if applicable. +** +** {F12554} The 6th parameter to the +** [sqlite3_set_authorizer | authorizer callback] is the name +** of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* NULL NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* Function Name NULL */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions {F12280} +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** The callback returns a UTF-8 rendering of the SQL statement text +** as the statement first begins executing. Additional callbacks occur +** as each triggersubprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger. +** +** The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. +** +** The sqlite3_profile() API is currently considered experimental and +** is subject to change or removal in a future release. +** +** The trigger reporting feature of the trace callback is considered +** experimental and is subject to change or removal in future releases. +** Future versions of SQLite might also add new trace callback +** invocations. +** +** INVARIANTS: +** +** {F12281} The callback function registered by [sqlite3_trace()] is +** whenever an SQL statement first begins to execute and +** whenever a trigger subprogram first begins to run. +** +** {F12282} Each call to [sqlite3_trace()] overrides the previously +** registered trace callback. +** +** {F12283} A NULL trace callback disables tracing. +** +** {F12284} The first argument to the trace callback is a copy of +** the pointer which was the 3rd argument to [sqlite3_trace()]. +** +** {F12285} The second argument to the trace callback is a +** zero-terminated UTF8 string containing the original text +** of the SQL statement as it was passed into [sqlite3_prepare_v2()] +** or the equivalent, or an SQL comment indicating the beginning +** of a trigger subprogram. +** +** {F12287} The callback function registered by [sqlite3_profile()] is invoked +** as each SQL statement finishes. +** +** {F12288} The first parameter to the profile callback is a copy of +** the 3rd parameter to [sqlite3_profile()]. +** +** {F12289} The second parameter to the profile callback is a +** zero-terminated UTF-8 string that contains the complete text of +** the SQL statement as it was processed by [sqlite3_prepare_v2()] +** or the equivalent. +** +** {F12290} The third parameter to the profile callback is an estimate +** of the number of nanoseconds of wall-clock time required to +** run the SQL statement from start to finish. +*/ +void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks {F12910} +** +** This routine configures a callback function - the +** progress callback - that is invoked periodically during long +** running calls to [sqlite3_exec()], [sqlite3_step()] and +** [sqlite3_get_table()]. An example use for this +** interface is to keep a GUI updated during a large query. +** +** If the progress callback returns non-zero, the opertion is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI dialog box. +** +** INVARIANTS: +** +** {F12911} The callback function registered by [sqlite3_progress_handler()] +** is invoked periodically during long running calls to +** [sqlite3_step()]. +** +** {F12912} The progress callback is invoked once for every N virtual +** machine opcodes, where N is the second argument to +** the [sqlite3_progress_handler()] call that registered +** the callback. What if N is less than 1? +** +** {F12913} The progress callback itself is identified by the third +** argument to [sqlite3_progress_handler()]. +** +** {F12914} The fourth argument [sqlite3_progress_handler()] is a +*** void pointer passed to the progress callback +** function each time it is invoked. +** +** {F12915} If a call to [sqlite3_step()] results in fewer than +** N opcodes being executed, +** then the progress callback is never invoked. {END} +** +** {F12916} Every call to [sqlite3_progress_handler()] +** overwrites any previously registere progress handler. +** +** {F12917} If the progress handler callback is NULL then no progress +** handler is invoked. +** +** {F12918} If the progress callback returns a result other than 0, then +** the behavior is a if [sqlite3_interrupt()] had been called. +*/ +void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection {F12700} +** +** These routines open an SQLite database file whose name +** is given by the filename argument. +** The filename argument is interpreted as UTF-8 +** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 +** in the native byte order for [sqlite3_open16()]. +** An [sqlite3*] handle is usually returned in *ppDb, even +** if an error occurs. The only exception is if SQLite is unable +** to allocate memory to hold the [sqlite3] object, a NULL will +** be written into *ppDb instead of a pointer to the [sqlite3] object. +** If the database is opened (and/or created) +** successfully, then [SQLITE_OK] is returned. Otherwise an +** error code is returned. The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error. +** +** The default encoding for the database will be UTF-8 if +** [sqlite3_open()] or [sqlite3_open_v2()] is called and +** UTF-16 in the native byte order if [sqlite3_open16()] is used. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [sqlite3*] handle should be released by passing it +** to [sqlite3_close()] when it is no longer required. +** +** The [sqlite3_open_v2()] interface works like [sqlite3_open()] +** except that it acccepts two additional parameters for additional control +** over the new database connection. The flags parameter can be +** one of: +** +**
    +**
  1. [SQLITE_OPEN_READONLY] +**
  2. [SQLITE_OPEN_READWRITE] +**
  3. [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE] +**
+** +** The first value opens the database read-only. +** If the database does not previously exist, an error is returned. +** The second option opens +** the database for reading and writing if possible, or reading only if +** if the file is write protected. In either case the database +** must already exist or an error is returned. The third option +** opens the database for reading and writing and creates it if it does +** not already exist. +** The third options is behavior that is always used for [sqlite3_open()] +** and [sqlite3_open16()]. +** +** If the filename is ":memory:", then an private +** in-memory database is created for the connection. This in-memory +** database will vanish when the database connection is closed. Future +** version of SQLite might make use of additional special filenames +** that begin with the ":" character. It is recommended that +** when a database filename really does begin with +** ":" that you prefix the filename with a pathname like "./" to +** avoid ambiguity. +** +** If the filename is an empty string, then a private temporary +** on-disk database will be created. This private database will be +** automatically deleted as soon as the database connection is closed. +** +** The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system +** interface that the new database connection should use. If the +** fourth parameter is a NULL pointer then the default [sqlite3_vfs] +** object is used. +** +** Note to windows users: The encoding used for the filename argument +** of [sqlite3_open()] and [sqlite3_open_v2()] must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** [sqlite3_open()] or [sqlite3_open_v2()]. +** +** INVARIANTS: +** +** {F12701} The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces create a new +** [database connection] associated with +** the database file given in their first parameter. +** +** {F12702} The filename argument is interpreted as UTF-8 +** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16 +** in the native byte order for [sqlite3_open16()]. +** +** {F12703} A successful invocation of [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] writes a pointer to a new +** [database connection] into *ppDb. +** +** {F12704} The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces return [SQLITE_OK] upon success, +** or an appropriate [error code] on failure. +** +** {F12706} The default text encoding for a new database created using +** [sqlite3_open()] or [sqlite3_open_v2()] will be UTF-8. +** +** {F12707} The default text encoding for a new database created using +** [sqlite3_open16()] will be UTF-16. +** +** {F12709} The [sqlite3_open(F,D)] interface is equivalent to +** [sqlite3_open_v2(F,D,G,0)] where the G parameter is +** [SQLITE_OPEN_READWRITE]|[SQLITE_OPEN_CREATE]. +** +** {F12711} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the +** bit value [SQLITE_OPEN_READONLY] then the database is opened +** for reading only. +** +** {F12712} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the +** bit value [SQLITE_OPEN_READWRITE] then the database is opened +** reading and writing if possible, or for reading only if the +** file is write protected by the operating system. +** +** {F12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the +** bit value [SQLITE_OPEN_CREATE] and the database does not +** previously exist, an error is returned. +** +** {F12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the +** bit value [SQLITE_OPEN_CREATE] and the database does not +** previously exist, then an attempt is made to create and +** initialize the database. +** +** {F12717} If the filename argument to [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] is ":memory:", then an private, +** ephemeral, in-memory database is created for the connection. +** Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required +** in sqlite3_open_v2()? +** +** {F12719} If the filename is an empty string, then a private, ephermeral +** on-disk database will be created. +** Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required +** in sqlite3_open_v2()? +** +** {F12721} The [database connection] created by +** [sqlite3_open_v2(F,D,G,V)] will use the +** [sqlite3_vfs] object identified by the V parameter, or +** the default [sqlite3_vfs] object is V is a NULL pointer. +*/ +int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Error Codes And Messages {F12800} +** +** The sqlite3_errcode() interface returns the numeric +** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] +** for the most recent failed sqlite3_* API call associated +** with [sqlite3] handle 'db'. If a prior API call failed but the +** most recent API call succeeded, the return value from sqlite3_errcode() +** is undefined. +** +** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF8 or UTF16 respectively. +** Memory to hold the error message string is managed internally. +** The application does not need to worry with freeing the result. +** However, the error string might be overwritten or deallocated b +** subsequent calls to other SQLite interface functions. +** +** INVARIANTS: +** +** {F12801} The [sqlite3_errcode(D)] interface returns the numeric +** [SQLITE_OK | result code] or +** [SQLITE_IOERR_READ | extended result code] +** for the most recent failed interface call associated +** with [sqlite3] handle D. +** +** {U12802} If a prior API call failed but the most recent API call +** succeeded, the return value from [sqlite3_errcode()], +** [sqlite3_errmsg()], and [sqlite3_errmsg16()] are undefined. +** +** {F12803} The [sqlite3_errmsg(D)] and [sqlite3_errmsg16(D)] +** interfaces return English-language text that describes +** the error in the mostly recently failed interface call, +** encoded as either UTF8 or UTF16 respectively. +** +** {U12804} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()] +** are only valid until the next SQLite interface call. +** +** {F12807} Calls to [sqlite3_errcode()], [sqlite3_errmsg()], and +** [sqlite3_errmsg16()] themselves do not affect the +** results of future invocations of these routines. +** +** {F12808} Calls to API routines that do not return an error code +** (example: [sqlite3_data_count()]) do not +** change the error code or message returned by +** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()]. +** +** {F12809} Interfaces that are not associated with a specific +** [database connection] (examples: +** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()] +** do not change the values returned by +** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()]. +*/ +int sqlite3_errcode(sqlite3 *db); +const char *sqlite3_errmsg(sqlite3*); +const void *sqlite3_errmsg16(sqlite3*); + +/* +** CAPI3REF: SQL Statement Object {F13000} +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represent single SQL statements. This +** object is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". +** +** The life of a statement object goes something like this: +** +**
    +**
  1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
  2. Bind values to host parameters using +** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+** +** Refer to documentation on individual methods above for additional +** information. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Compiling An SQL Statement {F13010} +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument "db" is an [database connection] +** obtained from a prior call to [sqlite3_open()], [sqlite3_open_v2()] +** or [sqlite3_open16()]. +** The second argument "zSql" is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. {END} +** +** 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 +** until the nByte-th byte, whichever comes first. {END} +** +** *pzTail is made to point to the first byte past the end of the +** first SQL statement in zSql. These routines only compiles the first +** statement in zSql, so *pzTail is left pointing to what remains +** uncompiled. +** +** *ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be +** set to NULL. If the input text contains no SQL (if the input +** is and empty string or a comment) then *ppStmt is set to NULL. +** {U13018} The calling procedure is responsible for deleting the +** compiled SQL statement +** using [sqlite3_finalize()] after it has finished with it. +** +** On success, [SQLITE_OK] is returned. Otherwise an +** [error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. {END} This causes the [sqlite3_step()] interface to +** behave a differently in two ways: +** +**
    +**
  1. +** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. If the schema has changed in +** a way that makes the statement no longer valid, [sqlite3_step()] will still +** return [SQLITE_SCHEMA]. But unlike the legacy behavior, +** [SQLITE_SCHEMA] is now a fatal error. Calling +** [sqlite3_prepare_v2()] again will not make the +** error go away. Note: use [sqlite3_errmsg()] to find the text +** of the parsing error that results in an [SQLITE_SCHEMA] return. {END} +**
  2. +** +**
  3. +** When an error occurs, +** [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. +** The legacy behavior was that [sqlite3_step()] would only return a generic +** [SQLITE_ERROR] result code and you would have to make a second call to +** [sqlite3_reset()] in order to find the underlying cause of the problem. +** With the "v2" prepare interfaces, the underlying reason for the error is +** returned immediately. +**
  4. +**
+** +** INVARIANTS: +** +** {F13011} The [sqlite3_prepare(db,zSql,...)] and +** [sqlite3_prepare_v2(db,zSql,...)] interfaces interpret the +** text in their zSql parameter as UTF-8. +** +** {F13012} The [sqlite3_prepare16(db,zSql,...)] and +** [sqlite3_prepare16_v2(db,zSql,...)] interfaces interpret the +** text in their zSql parameter as UTF-16 in the native byte order. +** +** {F13013} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)] +** and its variants is less than zero, then SQL text is +** read from zSql is read up to the first zero terminator. +** +** {F13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)] +** and its variants is non-negative, then nBytes bytes +** SQL text is read from zSql. +** +** {F13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants +** if the zSql input text contains more than one SQL statement +** and pzTail is not NULL, then *pzTail is made to point to the +** first byte past the end of the first SQL statement in zSql. +** What does *pzTail point to if there is one statement? +** +** {F13016} A successful call to [sqlite3_prepare_v2(db,zSql,N,ppStmt,...)] +** or one of its variants writes into *ppStmt a pointer to a new +** [prepared statement] or a pointer to NULL +** if zSql contains nothing other than whitespace or comments. +** +** {F13019} The [sqlite3_prepare_v2()] interface and its variants return +** [SQLITE_OK] or an appropriate [error code] upon failure. +*/ +int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPIREF: Retrieving Statement SQL {F13100} +** +** This intereface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement]. +** +** INVARIANTS: +** +** {F13101} If the [prepared statement] passed as +** the an argument to [sqlite3_sql()] was compiled +** compiled using either [sqlite3_prepare_v2()] or +** [sqlite3_prepare16_v2()], +** then [sqlite3_sql()] function returns a pointer to a +** zero-terminated string containing a UTF-8 rendering +** of the original SQL statement. +** +** {F13102} If the [prepared statement] passed as +** the an argument to [sqlite3_sql()] was compiled +** compiled using either [sqlite3_prepare()] or +** [sqlite3_prepare16()], +** then [sqlite3_sql()] function returns a NULL pointer. +** +** {F13103} The string returned by [sqlite3_sql(S)] is valid until the +** [prepared statement] S is deleted using [sqlite3_finalize(S)]. +*/ +const char *sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Dynamically Typed Value Object {F15000} +** +** SQLite uses the sqlite3_value object to represent all values +** that are or can be stored in a database table. +** SQLite uses dynamic typing for the values it stores. +** Values stored in sqlite3_value objects can be +** be integers, floating point values, strings, BLOBs, or NULL. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object {F16001} +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. A pointer to an sqlite3_context +** object is always first parameter to application-defined SQL functions. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements {F13500} +** +** In the SQL strings input to [sqlite3_prepare_v2()] and its +** variants, literals may be replace by a parameter in one +** of these forms: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :VVV +**
  • @VVV +**
  • $VVV +**
+** +** In the parameter forms shown above NNN is an integer literal, +** VVV alpha-numeric parameter name. +** The values of these parameters (also called "host parameter names" +** or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** The first argument to the sqlite3_bind_*() routines always +** is a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. The second +** argument is the index of the parameter to be set. The +** first parameter has an index of 1. When the same named +** parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_name()] API if desired. The index +** for "?NNN" parameters is the value of NNN. +** The NNN value must be between 1 and the compile-time +** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). +** +** The third argument is the value to bind to the parameter. +** +** In those +** routines that have a fourth argument, its value is the number of bytes +** in the parameter. To be clear: the value is the number of bytes +** in the value, not the number of characters. The number +** of bytes does not include the zero-terminator at the end of strings. +** If the fourth parameter is negative, the length of the string is +** number of bytes up to the first zero terminator. +** +** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** If the fifth argument has the value [SQLITE_TRANSIENT], then +** SQLite makes its own private copy of the data immediately, before +** the sqlite3_bind_*() routine returns. +** +** The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeros. A zeroblob uses a fixed amount of memory +** (just an integer to hold it size) while it is being processed. +** Zeroblobs are intended to serve as place-holders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | increment BLOB I/O] routines. A negative +** value for the zeroblob results in a zero-length BLOB. +** +** The sqlite3_bind_*() routines must be called after +** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and +** before [sqlite3_step()]. +** Bindings are not cleared by the [sqlite3_reset()] routine. +** Unbound parameters are interpreted as NULL. +** +** These routines return [SQLITE_OK] on success or an error code if +** anything goes wrong. [SQLITE_RANGE] is returned if the parameter +** index is out of range. [SQLITE_NOMEM] is returned if malloc fails. +** [SQLITE_MISUSE] might be returned if these routines are called on a +** virtual machine that is the wrong state or which has already been finalized. +** Detection of misuse is unreliable. Applications should not depend +** on SQLITE_MISUSE returns. SQLITE_MISUSE is intended to indicate a +** a logic error in the application. Future versions of SQLite might +** panic rather than return SQLITE_MISUSE. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13506} The [sqlite3_prepare | SQL statement compiler] recognizes +** tokens of the forms "?", "?NNN", "$VVV", ":VVV", and "@VVV" +** as SQL parameters, where NNN is any sequence of one or more +** digits and where VVV is any sequence of one or more +** alphanumeric characters or "::" optionally followed by +** a string containing no spaces and contained within parentheses. +** +** {F13509} The initial value of an SQL parameter is NULL. +** +** {F13512} The index of an "?" SQL parameter is one larger than the +** largest index of SQL parameter to the left, or 1 if +** the "?" is the leftmost SQL parameter. +** +** {F13515} The index of an "?NNN" SQL parameter is the integer NNN. +** +** {F13518} The index of an ":VVV", "$VVV", or "@VVV" SQL parameter is +** the same as the index of leftmost occurances of the same +** parameter, or one more than the largest index over all +** parameters to the left if this is the first occurrance +** of this parameter, or 1 if this is the leftmost parameter. +** +** {F13521} The [sqlite3_prepare | SQL statement compiler] fail with +** an [SQLITE_RANGE] error if the index of an SQL parameter +** is less than 1 or greater than SQLITE_MAX_VARIABLE_NUMBER. +** +** {F13524} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,V,...)] +** associate the value V with all SQL parameters having an +** index of N in the [prepared statement] S. +** +** {F13527} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,...)] +** override prior calls with the same values of S and N. +** +** {F13530} Bindings established by [sqlite3_bind_text | sqlite3_bind(S,...)] +** persist across calls to [sqlite3_reset(S)]. +** +** {F13533} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds the first L +** bytes of the blob or string pointed to by V, when L +** is non-negative. +** +** {F13536} In calls to [sqlite3_bind_text(S,N,V,L,D)] or +** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds characters +** from V through the first zero character when L is negative. +** +** {F13539} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special +** constant [SQLITE_STATIC], SQLite assumes that the value V +** is held in static unmanaged space that will not change +** during the lifetime of the binding. +** +** {F13542} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special +** constant [SQLITE_TRANSIENT], the routine makes a +** private copy of V value before it returns. +** +** {F13545} In calls to [sqlite3_bind_blob(S,N,V,L,D)], +** [sqlite3_bind_text(S,N,V,L,D)], or +** [sqlite3_bind_text16(S,N,V,L,D)] when D is a pointer to +** a function, SQLite invokes that function to destroy the +** V value after it has finished using the V value. +** +** {F13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound +** is a blob of L bytes, or a zero-length blob if L is negative. +*/ +int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +int sqlite3_bind_double(sqlite3_stmt*, int, double); +int sqlite3_bind_int(sqlite3_stmt*, int, int); +int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +int sqlite3_bind_null(sqlite3_stmt*, int); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of SQL Parameters {F13600} +** +** This routine can be used to find the number of SQL parameters +** in a prepared statement. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** place-holders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** This routine actually returns the index of the largest parameter. +** For all forms except ?NNN, this will correspond to the number of +** unique parameters. If parameters of the ?NNN are used, there may +** be gaps in the list. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13601} The [sqlite3_bind_parameter_count(S)] interface returns +** the largest index of all SQL parameters in the +** [prepared statement] S, or 0 if S +** contains no SQL parameters. +*/ +int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter {F13620} +** +** This routine returns a pointer to the name of the n-th +** SQL parameter in a [prepared statement]. +** SQL parameters of the form ":AAA" or "@AAA" or "$AAA" have a name +** which is the string ":AAA" or "@AAA" or "$VVV". +** In other words, the initial ":" or "$" or "@" +** is included as part of the name. +** Parameters of the form "?" or "?NNN" have no name. +** +** The first host parameter has an index of 1, not 0. +** +** If the value n is out of range or if the n-th parameter is +** nameless, then NULL is returned. The returned string is +** always in the UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13621} The [sqlite3_bind_parameter_name(S,N)] interface returns +** a UTF-8 rendering of the name of the SQL parameter in +** [prepared statement] S having index N, or +** NULL if there is no SQL parameter with index N or if the +** parameter with index N is an anonymous parameter "?" or +** a numbered parameter "?NNN". +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name {F13640} +** +** Return the index of an SQL parameter given its name. The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. A zero +** is returned if no matching parameter is found. The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +** +** INVARIANTS: +** +** {F13641} The [sqlite3_bind_parameter_index(S,N)] interface returns +** the index of SQL parameter in [prepared statement] +** S whose name matches the UTF-8 string N, or 0 if there is +** no match. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660} +** +** Contrary to the intuition of many, [sqlite3_reset()] does not +** reset the [sqlite3_bind_blob | bindings] on a +** [prepared statement]. Use this routine to +** reset all host parameters to NULL. +** +** INVARIANTS: +** +** {F13661} The [sqlite3_clear_bindings(S)] interface resets all +** SQL parameter bindings in [prepared statement] S +** back to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set {F13710} +** +** Return the number of columns in the result set returned by the +** [prepared statement]. This routine returns 0 +** if pStmt is an SQL statement that does not return data (for +** example an UPDATE). +** +** INVARIANTS: +** +** {F13711} The [sqlite3_column_count(S)] interface returns the number of +** columns in the result set generated by the +** [prepared statement] S, or 0 if S does not generate +** a result set. +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set {F13720} +** +** These routines return the name assigned to a particular column +** in the result set of a SELECT statement. The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF16 string. The first parameter is the +** [prepared statement] that implements the SELECT statement. +** The second parameter is the column number. The left-most column is +** number 0. +** +** The returned string pointer is valid until either the +** [prepared statement] is destroyed by [sqlite3_finalize()] +** or until the next call sqlite3_column_name() or sqlite3_column_name16() +** on the same column. +** +** If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +** +** INVARIANTS: +** +** {F13721} A successful invocation of the [sqlite3_column_name(S,N)] +** interface returns the name +** of the Nth column (where 0 is the left-most column) for the +** result set of [prepared statement] S as a +** zero-terminated UTF-8 string. +** +** {F13723} A successful invocation of the [sqlite3_column_name16(S,N)] +** interface returns the name +** of the Nth column (where 0 is the left-most column) for the +** result set of [prepared statement] S as a +** zero-terminated UTF-16 string in the native byte order. +** +** {F13724} The [sqlite3_column_name()] and [sqlite3_column_name16()] +** interfaces return a NULL pointer if they are unable to +** allocate memory memory to hold there normal return strings. +** +** {F13725} If the N parameter to [sqlite3_column_name(S,N)] or +** [sqlite3_column_name16(S,N)] is out of range, then the +** interfaces returns a NULL pointer. +** +** {F13726} The strings returned by [sqlite3_column_name(S,N)] and +** [sqlite3_column_name16(S,N)] are valid until the next +** call to either routine with the same S and N parameters +** or until [sqlite3_finalize(S)] is called. +** +** {F13727} When a result column of a [SELECT] statement contains +** an AS clause, the name of that column is the indentifier +** to the right of the AS keyword. +*/ +const char *sqlite3_column_name(sqlite3_stmt*, int N); +const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result {F13740} +** +** These routines provide a means to determine what column of what +** table in which database a result of a SELECT statement comes from. +** The name of the database or table or column can be returned as +** either a UTF8 or UTF16 string. The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** The returned string is valid until +** the [prepared statement] is destroyed using +** [sqlite3_finalize()] or until the same information is requested +** again in a different encoding. +** +** The names returned are the original un-aliased names of the +** database, table, and column. +** +** The first argument to the following calls is a [prepared statement]. +** These functions return information about the Nth column returned by +** the statement, where N is the second function argument. +** +** If the Nth column returned by the statement is an expression +** or subquery and is not a column value, then all of these functions +** return NULL. These routine might also return NULL if a memory +** allocation error occurs. Otherwise, they return the +** name of the attached database, table and column that query result +** column was extracted from. +** +** As with all other SQLite APIs, those postfixed with "16" return +** UTF-16 encoded strings, the other functions return UTF-8. {END} +** +** These APIs are only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +** +** {U13751} +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. +** +** INVARIANTS: +** +** {F13741} The [sqlite3_column_database_name(S,N)] interface returns either +** the UTF-8 zero-terminated name of the database from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13742} The [sqlite3_column_database_name16(S,N)] interface returns either +** the UTF-16 native byte order +** zero-terminated name of the database from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13743} The [sqlite3_column_table_name(S,N)] interface returns either +** the UTF-8 zero-terminated name of the table from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13744} The [sqlite3_column_table_name16(S,N)] interface returns either +** the UTF-16 native byte order +** zero-terminated name of the table from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13745} The [sqlite3_column_origin_name(S,N)] interface returns either +** the UTF-8 zero-terminated name of the table column from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13746} The [sqlite3_column_origin_name16(S,N)] interface returns either +** the UTF-16 native byte order +** zero-terminated name of the table column from which the +** Nth result column of [prepared statement] S +** is extracted, or NULL if the the Nth column of S is a +** general expression or if unable to allocate memory +** to store the name. +** +** {F13748} The return values from +** [sqlite3_column_database_name|column metadata interfaces] +** are valid +** for the lifetime of the [prepared statement] +** or until the encoding is changed by another metadata +** interface call for the same prepared statement and column. +** +** LIMITATIONS: +** +** {U13751} If two or more threads call one or more +** [sqlite3_column_database_name|column metadata interfaces] +** the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +const char *sqlite3_column_database_name(sqlite3_stmt*,int); +const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +const char *sqlite3_column_table_name(sqlite3_stmt*,int); +const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result {F13760} +** +** The first parameter is a [prepared statement]. +** If this statement is a SELECT statement and the Nth column of the +** returned result set of that SELECT is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned. If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** The returned string is always UTF-8 encoded. {END} +** For example, in the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** And the following statement compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** Then this routine would return the string "VARIANT" for the second +** result column (i==1), and a NULL pointer for the first result column +** (i==0). +** +** SQLite uses dynamic run-time typing. So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. Type +** is associated with individual values, not with the containers +** used to hold those values. +** +** INVARIANTS: +** +** {F13761} A successful call to [sqlite3_column_decltype(S,N)] +** returns a zero-terminated UTF-8 string containing the +** the declared datatype of the table column that appears +** as the Nth column (numbered from 0) of the result set to the +** [prepared statement] S. +** +** {F13762} A successful call to [sqlite3_column_decltype16(S,N)] +** returns a zero-terminated UTF-16 native byte order string +** containing the declared datatype of the table column that appears +** as the Nth column (numbered from 0) of the result set to the +** [prepared statement] S. +** +** {F13763} If N is less than 0 or N is greater than or equal to +** the number of columns in [prepared statement] S +** or if the Nth column of S is an expression or subquery rather +** than a table column or if a memory allocation failure +** occurs during encoding conversions, then +** calls to [sqlite3_column_decltype(S,N)] or +** [sqlite3_column_decltype16(S,N)] return NULL. +*/ +const char *sqlite3_column_decltype(sqlite3_stmt*,int); +const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement {F13200} +** +** After an [prepared statement] has been prepared with a call +** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of +** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], +** then this function must be called one or more times to evaluate the +** statement. +** +** The details of the behavior of this sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** In the lagacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** With the "v2" interface, any of the other [SQLITE_OK | result code] +** or [SQLITE_IOERR_READ | extended result code] might be returned as +** well. +** +** [SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. If the statement is a COMMIT +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a COMMIT and occurs within a +** explicit transaction then you should rollback the transaction before +** continuing. +** +** [SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** If the SQL statement being executed returns any data, then +** [SQLITE_ROW] is returned each time a new row of data is ready +** for processing by the caller. The values may be accessed using +** the [sqlite3_column_int | column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** [SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** With the legacy interface, a more specific error code (example: +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** Goofy Interface Alert: +** In the legacy interface, +** the sqlite3_step() API always returns a generic error code, +** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] +** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or +** [sqlite3_finalize()] in order to find one of the specific +** [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the +** more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +** +** INVARIANTS: +** +** {F13202} If [prepared statement] S is ready to be +** run, then [sqlite3_step(S)] advances that prepared statement +** until to completion or until it is ready to return another +** row of the result set or an interrupt or run-time error occurs. +** +** {F15304} When a call to [sqlite3_step(S)] causes the +** [prepared statement] S to run to completion, +** the function returns [SQLITE_DONE]. +** +** {F15306} When a call to [sqlite3_step(S)] stops because it is ready +** to return another row of the result set, it returns +** [SQLITE_ROW]. +** +** {F15308} If a call to [sqlite3_step(S)] encounters an +** [sqlite3_interrupt|interrupt] or a run-time error, +** it returns an appropraite error code that is not one of +** [SQLITE_OK], [SQLITE_ROW], or [SQLITE_DONE]. +** +** {F15310} If an [sqlite3_interrupt|interrupt] or run-time error +** occurs during a call to [sqlite3_step(S)] +** for a [prepared statement] S created using +** legacy interfaces [sqlite3_prepare()] or +** [sqlite3_prepare16()] then the function returns either +** [SQLITE_ERROR], [SQLITE_BUSY], or [SQLITE_MISUSE]. +*/ +int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set {F13770} +** +** Return the number of values in the current row of the result set. +** +** INVARIANTS: +** +** {F13771} After a call to [sqlite3_step(S)] that returns +** [SQLITE_ROW], the [sqlite3_data_count(S)] routine +** will return the same value as the +** [sqlite3_column_count(S)] function. +** +** {F13772} After [sqlite3_step(S)] has returned any value other than +** [SQLITE_ROW] or before [sqlite3_step(S)] has been +** called on the [prepared statement] for +** the first time since it was [sqlite3_prepare|prepared] +** or [sqlite3_reset|reset], the [sqlite3_data_count(S)] +** routine returns zero. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes {F10265} +** KEYWORDS: SQLITE_TEXT +** +** {F10266}Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
{END} +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Results Values From A Query {F13800} +** +** These routines form the "result set query" interface. +** +** These routines return information about +** a single column of the current result row of a query. In every +** case the first argument is a pointer to the +** [prepared statement] that is being +** evaluated (the [sqlite3_stmt*] that was returned from +** [sqlite3_prepare_v2()] or one of its variants) and +** the second argument is the index of the column for which information +** should be returned. The left-most column of the result set +** has an index of 0. +** +** If the SQL statement is not currently point to a valid row, or if the +** the column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] has been call subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** The sqlite3_column_type() routine returns +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** The value returned does not include the zero terminator at the end +** of the string. For clarity: the value returned is the number of +** bytes in the string, not the number of characters. +** +** Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero terminated. The return +** value from sqlite3_column_blob() for a zero-length blob is an arbitrary +** pointer, possibly even a NULL pointer. +** +** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() +** but leaves the result in UTF-16 in native byte order instead of UTF-8. +** The zero terminator is not included in this count. +** +** These routines attempt to convert the value where appropriate. For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to do the conversion +** automatically. The following table details the conversions that +** are applied: +** +**
+**
+**
Internal
Type
Requested
Type
Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is NULL pointer +**
NULL BLOB Result is NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as for INTEGER->TEXT +**
FLOAT INTEGER Convert from float to integer +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB Same as FLOAT->TEXT +**
TEXT INTEGER Use atoi() +**
TEXT FLOAT Use atof() +**
TEXT BLOB No change +**
BLOB INTEGER Convert to TEXT then use atoi() +**
BLOB FLOAT Convert to TEXT then use atof() +**
BLOB TEXT Add a zero terminator if needed +**
+** +** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** on equavalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
    +**
  • The initial content is a BLOB and sqlite3_column_text() +** or sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.

  • +** +**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.

  • +** +**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.

  • +**
+** +** Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer points to will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometime it is +** not possible and in those cases prior pointers are invalidated. +** +** The safest and easiest to remember policy is to invoke these routines +** in one of the following ways: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), +** or sqlite3_column_text16() first to force the result into the desired +** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to +** find the size of the result. Do not mix call to sqlite3_column_text() or +** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not +** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). +** +** The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. The memory space used to hold strings +** and blobs is freed automatically. Do not pass the pointers returned +** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM]. +** +** INVARIANTS: +** +** {F13803} The [sqlite3_column_blob(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a blob and then returns a +** pointer to the converted value. +** +** {F13806} The [sqlite3_column_bytes(S,N)] interface returns the +** number of bytes in the blob or string (exclusive of the +** zero terminator on the string) that was returned by the +** most recent call to [sqlite3_column_blob(S,N)] or +** [sqlite3_column_text(S,N)]. +** +** {F13809} The [sqlite3_column_bytes16(S,N)] interface returns the +** number of bytes in the string (exclusive of the +** zero terminator on the string) that was returned by the +** most recent call to [sqlite3_column_text16(S,N)]. +** +** {F13812} The [sqlite3_column_double(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a floating point value and +** returns a copy of that value. +** +** {F13815} The [sqlite3_column_int(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a 32-bit signed integer and +** returns a copy of that integer. +** +** {F13818} The [sqlite3_column_int64(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a 64-bit signed integer and +** returns a copy of that integer. +** +** {F13821} The [sqlite3_column_text(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a zero-terminated UTF-8 +** string and returns a pointer to that string. +** +** {F13824} The [sqlite3_column_text16(S,N)] interface converts the +** Nth column in the current row of the result set for +** [prepared statement] S into a zero-terminated 2-byte +** aligned UTF-16 native byte order +** string and returns a pointer to that string. +** +** {F13827} The [sqlite3_column_type(S,N)] interface returns +** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT], +** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for +** the Nth column in the current row of the result set for +** [prepared statement] S. +** +** {F13830} The [sqlite3_column_value(S,N)] interface returns a +** pointer to the [sqlite3_value] object that for the +** Nth column in the current row of the result set for +** [prepared statement] S. +*/ +const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +double sqlite3_column_double(sqlite3_stmt*, int iCol); +int sqlite3_column_int(sqlite3_stmt*, int iCol); +sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +int sqlite3_column_type(sqlite3_stmt*, int iCol); +sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object {F13300} +** +** The sqlite3_finalize() function is called to delete a +** [prepared statement]. If the statement was +** executed successfully, or not executed at all, then SQLITE_OK is returned. +** If execution of the statement failed then an +** [error code] or [extended error code] +** is returned. +** +** This routine can be called at any point during the execution of the +** [prepared statement]. If the virtual machine has not +** completed execution when this routine is called, that is like +** encountering an error or an interrupt. (See [sqlite3_interrupt()].) +** Incomplete updates may be rolled back and transactions cancelled, +** depending on the circumstances, and the +** [error code] returned will be [SQLITE_ABORT]. +** +** INVARIANTS: +** +** {F11302} The [sqlite3_finalize(S)] interface destroys the +** [prepared statement] S and releases all +** memory and file resources held by that object. +** +** {F11304} If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned an error, +** then [sqlite3_finalize(S)] returns that same error. +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object {F13330} +** +** The sqlite3_reset() function is called to reset a +** [prepared statement] object. +** back to its initial state, ready to be re-executed. +** Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** {F11332} The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** {F11334} If the most recent call to [sqlite3_step(S)] for +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** {F11336} If the most recent call to [sqlite3_step(S)] for +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** {F11338} The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on [prepared statement] S. +*/ +int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions {F16100} +** KEYWORDS: {function creation routines} +** +** These two functions (collectively known as +** "function creation routines") are used to add SQL functions or aggregates +** or to redefine the behavior of existing SQL functions or aggregates. The +** difference only between the two is that the second parameter, the +** name of the (scalar) function or aggregate, is encoded in UTF-8 for +** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). +** +** The first argument is the [database connection] that holds the +** SQL function or aggregate is to be added or redefined. If a single +** program uses more than one database handle internally, then SQL +** functions or aggregates must be added individually to each database +** handle with which they will be used. +** +** The second parameter is the name of the SQL function to be created +** or redefined. +** The length of the name is limited to 255 bytes, exclusive of the +** zero-terminator. Note that the name length limit is in bytes, not +** characters. Any attempt to create a function with a longer name +** will result in an SQLITE_ERROR error. +** +** The third parameter is the number of arguments that the SQL function or +** aggregate takes. If this parameter is negative, then the SQL function or +** aggregate may take any number of arguments. +** +** The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Any SQL function implementation should be able to work +** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. It is allowed to +** invoke sqlite3_create_function() or sqlite3_create_function16() multiple +** times with the same function but with different values of eTextRep. +** When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** If there is only a single implementation which does not care what +** text encoding is used, then the fourth argument should be +** [SQLITE_ANY]. +** +** The fifth parameter is an arbitrary pointer. The implementation +** of the function can gain access to this pointer using +** [sqlite3_user_data()]. +** +** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL +** function or aggregate. A scalar SQL function requires an implementation of +** the xFunc callback only, NULL pointers should be passed as the xStep +** and xFinal parameters. An aggregate SQL function requires an implementation +** of xStep and xFinal and NULL should be passed for xFunc. To delete an +** existing SQL function or aggregate, pass NULL for all three function +** callback. +** +** It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing perferred text encodings. SQLite will use +** the implementation most closely matches the way in which the +** SQL function is used. +** +** INVARIANTS: +** +** {F16103} The [sqlite3_create_function16()] interface behaves exactly +** like [sqlite3_create_function()] in every way except that it +** interprets the zFunctionName argument as +** zero-terminated UTF-16 native byte order instead of as a +** zero-terminated UTF-8. +** +** {F16106} +*/ +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); + +/* +** CAPI3REF: Text Encodings {F10267} +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Obsolete Functions +** +** These functions are all now obsolete. In order to maintain +** backwards compatibility with older code, we continue to support +** these functions. However, new development projects should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you want they do. +*/ +int sqlite3_aggregate_count(sqlite3_context*); +int sqlite3_expired(sqlite3_stmt*); +int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +int sqlite3_global_recover(void); +void sqlite3_thread_cleanup(void); +int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values {F15100} +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 4th parameter to these callbacks is an array of pointers to +** [sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work just like the corresponding +** [sqlite3_column_blob | sqlite3_column_* routines] except that +** these routines take a single [sqlite3_value*] pointer instead +** of an [sqlite3_stmt*] pointer and an integer column number. +** +** The sqlite3_value_text16() interface extracts a UTF16 string +** in the native byte-order of the host machine. The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF16 strings as big-endian and little-endian respectively. +** +** The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words if the value is a string that looks like a number) +** then the conversion is done. Otherwise no conversion occurs. The +** [SQLITE_INTEGER | datatype] after conversion is returned. +** +** Please pay particular attention to the fact that the pointer that +** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the sqlite3_value* parameters. +** Or, if the sqlite3_value* argument comes from the [sqlite3_column_value()] +** interface, then these routines should be called from the same thread +** that ran [sqlite3_column_value()]. +** +*/ +const void *sqlite3_value_blob(sqlite3_value*); +int sqlite3_value_bytes(sqlite3_value*); +int sqlite3_value_bytes16(sqlite3_value*); +double sqlite3_value_double(sqlite3_value*); +int sqlite3_value_int(sqlite3_value*); +sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +const unsigned char *sqlite3_value_text(sqlite3_value*); +const void *sqlite3_value_text16(sqlite3_value*); +const void *sqlite3_value_text16le(sqlite3_value*); +const void *sqlite3_value_text16be(sqlite3_value*); +int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context {F16210} +** +** The implementation of aggregate SQL functions use this routine to allocate +** a structure for storing their state. +** {F16211} The first time the sqlite3_aggregate_context() routine is +** is called for a particular aggregate, SQLite allocates nBytes of memory +** zeros that memory, and returns a pointer to it. +** {F16212} On second and subsequent calls to sqlite3_aggregate_context() +** for the same aggregate function index, the same buffer is returned. {END} +** The implementation +** of the aggregate can use the returned buffer to accumulate data. +** +** {F16213} SQLite automatically frees the allocated buffer when the aggregate +** query concludes. {END} +** +** The first parameter should be a copy of the +** [sqlite3_context | SQL function context] that is the first +** parameter to the callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions {F16240} +** +** {F16241} The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. {END} +** +** {U16243} This routine must be called from the same thread in which +** the application-defined function is running. +*/ +void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data {F16270} +** +** The following two functions may be used by scalar SQL functions to +** associate meta-data with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated meta-data may be preserved. This may +** be used, for example, to add a regular-expression matching scalar +** function. The compiled version of the regular expression is stored as +** meta-data associated with the SQL value passed as the regular expression +** pattern. The compiled regular expression can be reused on multiple +** invocations of the same function so that the original pattern string +** does not need to be recompiled on each invocation. +** +** {F16271} +** The sqlite3_get_auxdata() interface returns a pointer to the meta-data +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. +** {F16272} If no meta-data has been ever been set for the Nth +** argument of the function, or if the cooresponding function parameter +** has changed since the meta-data was set, then sqlite3_get_auxdata() +** returns a NULL pointer. +** +** {F16275} The sqlite3_set_auxdata() interface saves the meta-data +** pointed to by its 3rd parameter as the meta-data for the N-th +** argument of the application-defined function. {END} Subsequent +** calls to sqlite3_get_auxdata() might return this data, if it has +** not been destroyed. +** {F16277} If it is not NULL, SQLite will invoke the destructor +** function given by the 4th parameter to sqlite3_set_auxdata() on +** the meta-data when the corresponding function parameter changes +** or when the SQL statement completes, whichever comes first. {END} +** +** In practice, meta-data is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and SQL variables. +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +void *sqlite3_get_auxdata(sqlite3_context*, int N); +void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior {F10280} +** +** These are special value for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. See ticket #2191. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function {F16400} +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the +** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used +** to bind values to host parameters in prepared statements. +** Refer to the +** [sqlite3_bind_blob | sqlite3_bind_* documentation] for +** additional information. +** +** {F16402} The sqlite3_result_blob() interface sets the result from +** an application defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** {F16403} The sqlite3_result_zeroblob() inerfaces set the result of +** the application defined function to be a BLOB containing all zero +** bytes and N bytes in size, where N is the value of the 2nd parameter. +** +** {F16407} The sqlite3_result_double() interface sets the result from +** an application defined function to be a floating point value specified +** by its 2nd argument. +** +** {F16409} The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** {F16411} SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. {F16412} SQLite interprets the error +** message string from sqlite3_result_error() as UTF8. {F16413} SQLite +** interprets the string from sqlite3_result_error16() as UTF16 in native +** byte order. {F16414} If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** {F16415} If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** {F16417} The sqlite3_result_error() and sqlite3_result_error16() +** routines make a copy private copy of the error message text before +** they return. {END} Hence, the calling function can deallocate or +** modify the text after they return without harm. +** The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. By default, +** the error code is SQLITE_ERROR. +** +** {F16421} The sqlite3_result_toobig() interface causes SQLite +** to throw an error indicating that a string or BLOB is to long +** to represent. {F16422} The sqlite3_result_nomem() interface +** causes SQLite to throw an exception indicating that the a +** memory allocation failed. +** +** {F16431} The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** {F16432} The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** {F16437} The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** {F16441} The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** {F16442} SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** {F16444} If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** {F16447} If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. +** {F16451} If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or blob result when it has +** finished using that result. +** {F16453} If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_STATIC, then +** SQLite assumes that the text or blob result is constant space and +** does not copy the space or call a destructor when it has +** finished using that result. +** {F16454} If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained from +** from [sqlite3_malloc()] before it returns. +** +** {F16461} The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy the [sqlite3_value] +** object specified by the 2nd parameter. {F16463} The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** +** {U16491} These routines are called from within the different thread +** than the one containing the application-defined function that recieved +** the [sqlite3_context] pointer, the results are undefined. +*/ +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_double(sqlite3_context*, double); +void sqlite3_result_error(sqlite3_context*, const char*, int); +void sqlite3_result_error16(sqlite3_context*, const void*, int); +void sqlite3_result_error_toobig(sqlite3_context*); +void sqlite3_result_error_nomem(sqlite3_context*); +void sqlite3_result_error_code(sqlite3_context*, int); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences {F16600} +** +** {F16601} +** These functions are used to add new collation sequences to the +** [sqlite3*] handle specified as the first argument. +** +** {F16602} +** The name of the new collation sequence is specified as a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string for sqlite3_create_collation16(). {F16603} In all cases +** the name is passed as the second function argument. +** +** {F16604} +** The third argument may be one of the constants [SQLITE_UTF8], +** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied +** routine expects to be passed pointers to strings encoded using UTF-8, +** UTF-16 little-endian or UTF-16 big-endian respectively. {F16605} The +** third argument might also be [SQLITE_UTF16_ALIGNED] to indicate that +** the routine expects pointers to 16-bit word aligned strings +** of UTF16 in the native byte order of the host computer. +** +** {F16607} +** A pointer to the user supplied routine must be passed as the fifth +** argument. {F16609} If it is NULL, this is the same as deleting the collation +** sequence (so that SQLite cannot call it anymore). +** {F16611} Each time the application +** supplied function is invoked, it is passed a copy of the void* passed as +** the fourth argument to sqlite3_create_collation() or +** sqlite3_create_collation16() as its first parameter. +** +** {F16612} +** The remaining arguments to the application-supplied routine are two strings, +** each represented by a (length, data) pair and encoded in the encoding +** that was passed as the third argument when the collation sequence was +** registered. {END} The application defined collation routine should +** return negative, zero or positive if +** the first string is less than, equal to, or greater than the second +** string. i.e. (STRING1 - STRING2). +** +** {F16615} +** The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** excapt that it takes an extra argument which is a destructor for +** the collation. {F16617} The destructor is called when the collation is +** destroyed and is passed a copy of the fourth parameter void* pointer +** of the sqlite3_create_collation_v2(). +** {F16618} Collations are destroyed when +** they are overridden by later calls to the collation creation functions +** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. +*/ +int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); +int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +int sqlite3_create_collation16( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks {F16700} +** +** {F16701} +** To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** database handle to be called whenever an undefined collation sequence is +** required. +** +** {F16702} +** If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used, the names +** are passed as UTF-16 in machine native byte order. {F16704} A call to either +** function replaces any existing callback. +** +** {F16705} When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). {F16706} The second argument is the database +** handle. {F16707} The third argument is one of [SQLITE_UTF8], +** [SQLITE_UTF16BE], or [SQLITE_UTF16LE], indicating the most +** desirable form of the collation sequence function required. +** {F16708} The fourth parameter is the name of the +** required collation sequence. {END} +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +/* +** CAPI3REF: Suspend Execution For A Short Time {F10530} +** +** {F10531} The sqlite3_sleep() function +** causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** {F10532} If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. {F10533} The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** {F10534} SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. {END} +*/ +int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310} +** +** If this global variable is made to point to a string which is +** the name of a folder (a.ka. directory), then all temporary files +** created by SQLite will be placed in that directory. If this variable +** is NULL pointer, then SQLite does a search for an appropriate temporary +** file directory. +** +** It is not safe to modify this variable once a database connection +** has been opened. It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been call and remain unchanged thereafter. +*/ +SQLITE_EXTERN char *sqlite3_temp_directory; + +/* +** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930} +** +** The sqlite3_get_autocommit() interfaces returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. Autocommit mode is on +** by default. Autocommit mode is disabled by a [BEGIN] statement. +** Autocommit mode is reenabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transactions (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out if SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** INVARIANTS: +** +** {F12931} The [sqlite3_get_autocommit()] interface returns non-zero or +** zero if the given database connection is or is not in autocommit +** mode, respectively. +** +** {F12932} Autocommit mode is on by default. +** +** {F12933} Autocommit mode is disabled by a successful [BEGIN] statement. +** +** {F12934} Autocommit mode is enabled by a successful [COMMIT] or [ROLLBACK] +** statement. +** +** +** LIMITATIONS: +*** +** {U12936} If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120} +** +** {F13121} The sqlite3_db_handle interface +** returns the [sqlite3*] database handle to which a +** [prepared statement] belongs. +** {F13122} the database handle returned by sqlite3_db_handle +** is the same database handle that was +** the first argument to the [sqlite3_prepare_v2()] or its variants +** that was used to create the statement in the first place. +*/ +sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks {F12950} +** +** {F12951} The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is committed. +** {F12952} Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** {F12953} The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is committed. +** {F12954} Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** {F12956} The pArg argument is passed through +** to the callback. {F12957} If the callback on a commit hook function +** returns non-zero, then the commit is converted into a rollback. +** +** {F12958} If another function was previously registered, its +** pArg value is returned. Otherwise NULL is returned. +** +** {F12959} Registering a NULL function disables the callback. +** +** {F12961} For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** {F12962} The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** {F12964} The rollback callback is not invoked if a transaction is +** rolled back because a commit callback returned non-zero. +** Check on this {END} +** +** These are experimental interfaces and are subject to change. +*/ +void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks {F12970} +** +** {F12971} The sqlite3_update_hook() interface +** registers a callback function with the database connection identified by the +** first argument to be invoked whenever a row is updated, inserted or deleted. +** {F12972} Any callback set by a previous call to this function for the same +** database connection is overridden. +** +** {F12974} The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. +** {F12976} The first argument to the callback is +** a copy of the third argument to sqlite3_update_hook(). +** {F12977} The second callback +** argument is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], +** depending on the operation that caused the callback to be invoked. +** {F12978} The third and +** fourth arguments to the callback contain pointers to the database and +** table name containing the affected row. +** {F12979} The final callback parameter is +** the rowid of the row. +** {F12981} In the case of an update, this is the rowid after +** the update takes place. +** +** {F12983} The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence). +** +** {F12984} If another function was previously registered, its pArg value +** is returned. {F12985} Otherwise NULL is returned. +*/ +void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330} +** +** {F10331} +** This routine enables or disables the sharing of the database cache +** and schema data structures between connections to the same database. +** {F10332} +** Sharing is enabled if the argument is true and disabled if the argument +** is false. +** +** {F10333} Cache sharing is enabled and disabled +** for an entire process. {END} This is a change as of SQLite version 3.5.0. +** In prior versions of SQLite, sharing was +** enabled or disabled for each thread separately. +** +** {F10334} +** The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** {F10335} Existing database connections continue use the sharing mode +** that was in effect at the time they were opened. {END} +** +** Virtual tables cannot be used with a shared cache. {F10336} When shared +** cache is enabled, the [sqlite3_create_module()] API used to register +** virtual tables will always return an error. {END} +** +** {F10337} This routine returns [SQLITE_OK] if shared cache was +** enabled or disabled successfully. {F10338} An [error code] +** is returned otherwise. {END} +** +** {F10339} Shared cache is disabled by default. {END} But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +*/ +int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory {F17340} +** +** {F17341} The sqlite3_release_memory() interface attempts to +** free N bytes of heap memory by deallocating non-essential memory +** allocations held by the database labrary. {END} Memory used +** to cache database pages to improve performance is an example of +** non-essential memory. {F16342} sqlite3_release_memory() returns +** the number of bytes actually freed, which might be more or less +** than the amount requested. +*/ +int sqlite3_release_memory(int); + +/* +** CAPI3REF: Impose A Limit On Heap Size {F17350} +** +** {F16351} The sqlite3_soft_heap_limit() interface +** places a "soft" limit on the amount of heap memory that may be allocated +** by SQLite. {F16352} If an internal allocation is requested +** that would exceed the soft heap limit, [sqlite3_release_memory()] is +** invoked one or more times to free up some space before the allocation +** is made. {END} +** +** {F16353} The limit is called "soft", because if +** [sqlite3_release_memory()] cannot +** free sufficient memory to prevent the limit from being exceeded, +** the memory is allocated anyway and the current operation proceeds. +** +** {F16354} +** A negative or zero value for N means that there is no soft heap limit and +** [sqlite3_release_memory()] will only be called when memory is exhausted. +** {F16355} The default value for the soft heap limit is zero. +** +** SQLite makes a best effort to honor the soft heap limit. +** {F16356} But if the soft heap limit cannot honored, execution will +** continue without error or notification. {END} This is why the limit is +** called a "soft" limit. It is advisory only. +** +** Prior to SQLite version 3.5.0, this routine only constrained the memory +** allocated by a single thread - the same thread in which this routine +** runs. Beginning with SQLite version 3.5.0, the soft heap limit is +** applied to all threads. {F16357} The value specified for the soft heap limit +** is an upper bound on the total memory allocation for all threads. {END} In +** version 3.5.0 there is no mechanism for limiting the heap usage for +** individual threads. +*/ +void sqlite3_soft_heap_limit(int); + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table {F12850} +** +** This routine +** returns meta-data about a specific column of a specific database +** table accessible using the connection handle passed as the first function +** argument. +** +** The column is identified by the second, third and fourth parameters to +** this function. The second parameter is either the name of the database +** (i.e. "main", "temp" or an attached database) containing the specified +** table or NULL. If it is NULL, then all attached databases are searched +** for the table using the same algorithm as the database engine uses to +** resolve unqualified table references. +** +** The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** Meta information is returned by writing to the memory locations passed as +** the 5th and subsequent parameters to this function. Any of these +** arguments may be NULL, in which case the corresponding element of meta +** information is ommitted. +** +**
+** Parameter     Output Type      Description
+** -----------------------------------
+**
+**   5th         const char*      Data type
+**   6th         const char*      Name of the default collation sequence 
+**   7th         int              True if the column has a NOT NULL constraint
+**   8th         int              True if the column is part of the PRIMARY KEY
+**   9th         int              True if the column is AUTOINCREMENT
+** 
+** +** +** The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any sqlite API function. +** +** If the specified table is actually a view, then an error is returned. +** +** If the specified column is "rowid", "oid" or "_rowid_" and an +** INTEGER PRIMARY KEY column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. If there is no +** explicitly declared IPK column, then the output parameters are set as +** follows: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
+** +** This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an SQLITE error code is returned and an error message +** left in the database handle (to be retrieved using sqlite3_errmsg()). +** +** This API is only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension {F12600} +** +** {F12601} The sqlite3_load_extension() interface +** attempts to load an SQLite extension library contained in the file +** zFile. {F12602} The entry point is zProc. {F12603} zProc may be 0 +** in which case the name of the entry point defaults +** to "sqlite3_extension_init". +** +** {F12604} The sqlite3_load_extension() interface shall +** return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** +** {F12605} +** If an error occurs and pzErrMsg is not 0, then the +** sqlite3_load_extension() interface shall attempt to fill *pzErrMsg with +** error message text stored in memory obtained from [sqlite3_malloc()]. +** {END} The calling function should free this memory +** by calling [sqlite3_free()]. +** +** {F12606} +** Extension loading must be enabled using [sqlite3_enable_load_extension()] +** prior to calling this API or an error will be returned. +*/ +int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading {F12620} +** +** So as not to open security holes in older applications that are +** unprepared to deal with extension loading, and as a means of disabling +** extension loading while evaluating user-entered SQL, the following +** API is provided to turn the [sqlite3_load_extension()] mechanism on and +** off. {F12622} It is off by default. {END} See ticket #1863. +** +** {F12621} Call the sqlite3_enable_load_extension() routine +** with onoff==1 to turn extension loading on +** and call it with onoff==0 to turn it back off again. {END} +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640} +** +** {F12641} This function +** registers an extension entry point that is automatically invoked +** whenever a new database connection is opened using +** [sqlite3_open()], [sqlite3_open16()], or [sqlite3_open_v2()]. {END} +** +** This API can be invoked at program startup in order to register +** one or more statically linked extensions that will be available +** to all new database connections. +** +** {F12642} Duplicate extensions are detected so calling this routine multiple +** times with the same extension is harmless. +** +** {F12643} This routine stores a pointer to the extension in an array +** that is obtained from sqlite_malloc(). {END} If you run a memory leak +** checker on your program and it reports a leak because of this +** array, then invoke [sqlite3_reset_auto_extension()] prior +** to shutdown to free the memory. +** +** {F12644} Automatic extensions apply across all threads. {END} +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +int sqlite3_auto_extension(void *xEntryPoint); + + +/* +** CAPI3REF: Reset Automatic Extension Loading {F12660} +** +** {F12661} This function disables all previously registered +** automatic extensions. {END} This +** routine undoes the effect of all prior [sqlite3_auto_extension()] +** calls. +** +** {F12662} This call disabled automatic extensions in all threads. {END} +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +void sqlite3_reset_auto_extension(void); + + +/* +****** EXPERIMENTAL - subject to change without notice ************** +** +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stablizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** A module is a class of virtual tables. Each module is defined +** by an instance of the following structure. This structure consists +** mostly of methods for the module. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); +}; + +/* +** The sqlite3_index_info structure and its substructures is used to +** pass information into and receive the reply from the xBestIndex +** method of an sqlite3_module. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** The aConstraint[] array records WHERE clause constraints of the +** form: +** +** column OP expr +** +** Where OP is =, <, <=, >, or >=. +** The particular operator is stored +** in aConstraint[].op. The index of the column is stored in +** aConstraint[].iColumn. aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot. +** +** The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** The aConstraint[] array only reports WHERE clause terms in the correct +** form that refer to the particular virtual table being queried. +** +** Information about the ORDER BY clause is stored in aOrderBy[]. +** Each term of aOrderBy records a column of the ORDER BY clause. +** +** The xBestIndex method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite. +** +** The idxNum and idxPtr values are recorded and passed into xFilter. +** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from xFilter will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** The estimatedCost value is an estimate of the cost of doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +*/ +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ +}; +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** This routine is used to register a new module name with an SQLite +** connection. Module names must be registered before creating new +** virtual tables on the module, or before using preexisting virtual +** tables of the module. +*/ +int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void * /* Client data for xCreate/xConnect */ +); + +/* +** This routine is identical to the sqlite3_create_module() method above, +** except that it allows a destructor function to be specified. It is +** even more experimental than the rest of the virtual tables API. +*/ +int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void *, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** Every module implementation uses a subclass of the following structure +** to describe a particular instance of the module. Each subclass will +** be tailored to the specific needs of the module implementation. The +** purpose of this superclass is to define certain fields that are common +** to all module implementations. +** +** Virtual tables methods can set an error message by assigning a +** string obtained from sqlite3_mprintf() to zErrMsg. The method should +** take care that any prior string is freed by a call to sqlite3_free() +** prior to assigning a new string to zErrMsg. After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note +** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field +** since virtual tables are commonly implemented in loadable extensions which +** do not have access to sqlite3MPrintf() or sqlite3Free(). +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Used internally */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* Every module implementation uses a subclass of the following structure +** to describe cursors that point into the virtual table and are used +** to loop through the virtual table. Cursors are created using the +** xOpen method of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** The xCreate and xConnect methods of a module use the following API +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); + +/* +** Virtual tables can provide alternative implementations of functions +** using the xFindFunction method. But global versions of those functions +** must exist in order to be overloaded. +** +** This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created. The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a place-holder function that can be overloaded +** by virtual tables. +** +** This API should be considered part of the virtual table interface, +** which is experimental and subject to change. +*/ +int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +** +****** EXPERIMENTAL - subject to change without notice ************** +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB {F17800} +** +** An instance of the following opaque structure is used to +** represent an blob-handle. A blob-handle is created by +** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. +** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the blob. +** The [sqlite3_blob_bytes()] interface returns the size of the +** blob in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O {F17810} +** +** {F17811} This interfaces opens a handle to the blob located +** in row iRow,, column zColumn, table zTable in database zDb; +** in other words, the same blob that would be selected by: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
+** 
{END} +** +** {F17812} If the flags parameter is non-zero, the blob is opened for +** read and write access. If it is zero, the blob is opened for read +** access. {END} +** +** {F17813} On success, [SQLITE_OK] is returned and the new +** [sqlite3_blob | blob handle] is written to *ppBlob. +** {F17814} Otherwise an error code is returned and +** any value written to *ppBlob should not be used by the caller. +** {F17815} This function sets the database-handle error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +** We should go through and mark all interfaces that behave this +** way with a similar statement +*/ +int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Close A BLOB Handle {F17830} +** +** Close an open [sqlite3_blob | blob handle]. +** +** {F17831} Closing a BLOB shall cause the current transaction to commit +** if there are no other BLOBs, no pending prepared statements, and the +** database connection is in autocommit mode. +** {F17832} If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. {END} +** Closing the BLOB often forces the changes +** out to disk and so if any I/O errors occur, they will likely occur +** at the time when the BLOB is closed. {F17833} Any errors that occur during +** closing are reported as a non-zero return value. +** +** {F17839} The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed. +*/ +int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB {F17805} +** +** {F16806} Return the size in bytes of the blob accessible via the open +** [sqlite3_blob | blob-handle] passed as an argument. +*/ +int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally {F17850} +** +** This function is used to read data from an open +** [sqlite3_blob | blob-handle] into a caller supplied buffer. +** {F17851} n bytes of data are copied into buffer +** z from the open blob, starting at offset iOffset. +** +** {F17852} If offset iOffset is less than n bytes from the end of the blob, +** [SQLITE_ERROR] is returned and no data is read. {F17853} If n is +** less than zero [SQLITE_ERROR] is returned and no data is read. +** +** {F17854} On success, SQLITE_OK is returned. Otherwise, an +** [error code] or an [extended error code] is returned. +*/ +int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally {F17870} +** +** This function is used to write data into an open +** [sqlite3_blob | blob-handle] from a user supplied buffer. +** {F17871} n bytes of data are copied from the buffer +** pointed to by z into the open blob, starting at offset iOffset. +** +** {F17872} If the [sqlite3_blob | blob-handle] passed as the first argument +** was not opened for writing (the flags parameter to [sqlite3_blob_open()] +*** was zero), this function returns [SQLITE_READONLY]. +** +** {F17873} This function may only modify the contents of the blob; it is +** not possible to increase the size of a blob using this API. +** {F17874} If offset iOffset is less than n bytes from the end of the blob, +** [SQLITE_ERROR] is returned and no data is written. {F17875} If n is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** +** {F17876} On success, SQLITE_OK is returned. Otherwise, an +** [error code] or an [extended error code] is returned. +*/ +int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects {F11200} +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** {F11201} The sqlite3_vfs_find() interface returns a pointer to +** a VFS given its name. {F11202} Names are case sensitive. +** {F11203} Names are zero-terminated UTF-8 strings. +** {F11204} If there is no match, a NULL +** pointer is returned. {F11205} If zVfsName is NULL then the default +** VFS is returned. {END} +** +** {F11210} New VFSes are registered with sqlite3_vfs_register(). +** {F11211} Each new VFS becomes the default VFS if the makeDflt flag is set. +** {F11212} The same VFS can be registered multiple times without injury. +** {F11213} To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. {U11214} If two different VFSes with the +** same name are registered, the behavior is undefined. {U11215} If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** {F11220} Unregister a VFS with the sqlite3_vfs_unregister() interface. +** {F11221} If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary. +*/ +sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes {F17000} +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. The following +** implementations are available in the SQLite core: +** +**
    +**
  • SQLITE_MUTEX_OS2 +**
  • SQLITE_MUTEX_PTHREAD +**
  • SQLITE_MUTEX_W32 +**
  • SQLITE_MUTEX_NOOP +**
+** +** The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. The SQLITE_MUTEX_OS2, +** SQLITE_MUTEX_PTHREAD, and SQLITE_MUTEX_W32 implementations +** are appropriate for use on os/2, unix, and windows. +** +** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. The +** mutex interface routines defined here become external +** references in the SQLite library for which implementations +** must be provided by the application. This facility allows an +** application that links against SQLite to provide its own mutex +** implementation without having to modify the SQLite core. +** +** {F17011} The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. {F17012} If it returns NULL +** that means that a mutex could not be allocated. {F17013} SQLite +** will unwind its stack and return an error. {F17014} The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
    +**
  • SQLITE_MUTEX_FAST +**
  • SQLITE_MUTEX_RECURSIVE +**
  • SQLITE_MUTEX_STATIC_MASTER +**
  • SQLITE_MUTEX_STATIC_MEM +**
  • SQLITE_MUTEX_STATIC_MEM2 +**
  • SQLITE_MUTEX_STATIC_PRNG +**
  • SQLITE_MUTEX_STATIC_LRU +**
{END} +** +** {F17015} The first two constants cause sqlite3_mutex_alloc() to create +** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END} +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. {F17016} But SQLite will only request a recursive mutex in +** cases where it really needs one. {END} If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return +** a pointer to a static preexisting mutex. {END} Four static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. {F17034} But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. {END} +** +** {F17019} The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every +** dynamic mutex that it allocates. {U17021} The dynamic mutexes must not be in +** use when they are deallocated. {U17022} Attempting to deallocate a static +** mutex results in undefined behavior. {F17023} SQLite never deallocates +** a static mutex. {END} +** +** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. {F17024} If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns SQLITE_OK +** upon successful entry. {F17026} Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** {F17027} In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter. {U17028} If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** {F17029} SQLite will never exhibit +** such behavior in its own use of mutexes. {END} +** +** Some systems (ex: windows95) do not the operation implemented by +** sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() will +** always return SQLITE_BUSY. {F17030} The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior. {END} +** +** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. {U17032} The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. {F17033} SQLite will +** never do either. {END} +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +sqlite3_mutex *sqlite3_mutex_alloc(int); +void sqlite3_mutex_free(sqlite3_mutex*); +void sqlite3_mutex_enter(sqlite3_mutex*); +int sqlite3_mutex_try(sqlite3_mutex*); +void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Verifcation Routines {F17080} +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. {F17081} The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. {F17082} The core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. {U17087} External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** {F17083} These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. {END} +** +** {X17084} The implementation is not required to provided versions of these +** routines that actually work. +** If the implementation does not provide working +** versions of these routines, it should at least provide stubs +** that always return true so that one does not get spurious +** assertion failures. {END} +** +** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. {END} This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But the +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +int sqlite3_mutex_held(sqlite3_mutex*); +int sqlite3_mutex_notheld(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Types {F17001} +** +** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. {END} +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MASTER 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* sqlite3_release_memory() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ + +/* +** CAPI3REF: Low-Level Control Of Database Files {F11300} +** +** {F11301} The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. {F11302} The +** name of the database is the name assigned to the database by the +** ATTACH SQL command that opened the +** database. {F11303} To control the main database file, use the name "main" +** or a NULL pointer. {F11304} The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. {F11305} The return value of the xFileControl +** method becomes the return value of this routine. +** +** {F11306} If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. {F11307} This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. {U11308} The underlying xFileControl method might +** also return SQLITE_ERROR. {U11309} There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. {END} +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface {F11400} +** +** The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. The first parameter a operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes {F11410} +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meansing are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FAULT_CONFIG 1 +#define SQLITE_TESTCTRL_FAULT_FAILURES 2 +#define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES 3 +#define SQLITE_TESTCTRL_FAULT_PENDING 4 + + + + + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif +#endif diff --git a/client/src/thirdparty/sqlite-3.4.2/src/sqlite3ext.h b/client/src/thirdparty/sqlite-3.4.2/src/sqlite3ext.h new file mode 100644 index 0000000..5d4c2de --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/sqlite3ext.h @@ -0,0 +1,350 @@ +/* +** 2006 June 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the SQLite interface for use by +** shared libraries that want to be imported as extensions into +** an SQLite instance. Shared libraries that intend to be loaded +** as extensions by SQLite should #include this file instead of +** sqlite3.h. +** +** @(#) $Id: sqlite3ext.h,v 1.17 2007/08/31 16:11:36 drh Exp $ +*/ +#ifndef _SQLITE3EXT_H_ +#define _SQLITE3EXT_H_ +#include "sqlite3.h" + +typedef struct sqlite3_api_routines sqlite3_api_routines; + +/* +** The following structure hold pointers to all of the SQLite API +** routines. +** +** WARNING: In order to maintain backwards compatibility, add new +** interfaces to the end of this structure only. If you insert new +** interfaces in the middle of this structure, then older different +** versions of SQLite will not be able to load each others shared +** libraries! +*/ +struct sqlite3_api_routines { + void * (*aggregate_context)(sqlite3_context*,int nBytes); + int (*aggregate_count)(sqlite3_context*); + int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); + int (*bind_double)(sqlite3_stmt*,int,double); + int (*bind_int)(sqlite3_stmt*,int,int); + int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); + int (*bind_null)(sqlite3_stmt*,int); + int (*bind_parameter_count)(sqlite3_stmt*); + int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); + const char * (*bind_parameter_name)(sqlite3_stmt*,int); + int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); + int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); + int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); + int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); + int (*busy_timeout)(sqlite3*,int ms); + int (*changes)(sqlite3*); + int (*close)(sqlite3*); + int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*)); + int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*)); + const void * (*column_blob)(sqlite3_stmt*,int iCol); + int (*column_bytes)(sqlite3_stmt*,int iCol); + int (*column_bytes16)(sqlite3_stmt*,int iCol); + int (*column_count)(sqlite3_stmt*pStmt); + const char * (*column_database_name)(sqlite3_stmt*,int); + const void * (*column_database_name16)(sqlite3_stmt*,int); + const char * (*column_decltype)(sqlite3_stmt*,int i); + const void * (*column_decltype16)(sqlite3_stmt*,int); + double (*column_double)(sqlite3_stmt*,int iCol); + int (*column_int)(sqlite3_stmt*,int iCol); + sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); + const char * (*column_name)(sqlite3_stmt*,int); + const void * (*column_name16)(sqlite3_stmt*,int); + const char * (*column_origin_name)(sqlite3_stmt*,int); + const void * (*column_origin_name16)(sqlite3_stmt*,int); + const char * (*column_table_name)(sqlite3_stmt*,int); + const void * (*column_table_name16)(sqlite3_stmt*,int); + const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); + const void * (*column_text16)(sqlite3_stmt*,int iCol); + int (*column_type)(sqlite3_stmt*,int iCol); + sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); + void * (*commit_hook)(sqlite3*,int(*)(void*),void*); + int (*complete)(const char*sql); + int (*complete16)(const void*sql); + int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); + int (*create_collation16)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*)); + int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); + int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*)); + int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); + int (*data_count)(sqlite3_stmt*pStmt); + sqlite3 * (*db_handle)(sqlite3_stmt*); + int (*declare_vtab)(sqlite3*,const char*); + int (*enable_shared_cache)(int); + int (*errcode)(sqlite3*db); + const char * (*errmsg)(sqlite3*); + const void * (*errmsg16)(sqlite3*); + int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); + int (*expired)(sqlite3_stmt*); + int (*finalize)(sqlite3_stmt*pStmt); + void (*free)(void*); + void (*free_table)(char**result); + int (*get_autocommit)(sqlite3*); + void * (*get_auxdata)(sqlite3_context*,int); + int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); + int (*global_recover)(void); + void (*interruptx)(sqlite3*); + sqlite_int64 (*last_insert_rowid)(sqlite3*); + const char * (*libversion)(void); + int (*libversion_number)(void); + void *(*malloc)(int); + char * (*mprintf)(const char*,...); + int (*open)(const char*,sqlite3**); + int (*open16)(const void*,sqlite3**); + int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); + void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); + void *(*realloc)(void*,int); + int (*reset)(sqlite3_stmt*pStmt); + void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_double)(sqlite3_context*,double); + void (*result_error)(sqlite3_context*,const char*,int); + void (*result_error16)(sqlite3_context*,const void*,int); + void (*result_int)(sqlite3_context*,int); + void (*result_int64)(sqlite3_context*,sqlite_int64); + void (*result_null)(sqlite3_context*); + void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); + void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); + void (*result_value)(sqlite3_context*,sqlite3_value*); + void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); + int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*); + void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); + char * (*snprintf)(int,char*,const char*,...); + int (*step)(sqlite3_stmt*); + int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*); + void (*thread_cleanup)(void); + int (*total_changes)(sqlite3*); + void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); + int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); + void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*); + void * (*user_data)(sqlite3_context*); + const void * (*value_blob)(sqlite3_value*); + int (*value_bytes)(sqlite3_value*); + int (*value_bytes16)(sqlite3_value*); + double (*value_double)(sqlite3_value*); + int (*value_int)(sqlite3_value*); + sqlite_int64 (*value_int64)(sqlite3_value*); + int (*value_numeric_type)(sqlite3_value*); + const unsigned char * (*value_text)(sqlite3_value*); + const void * (*value_text16)(sqlite3_value*); + const void * (*value_text16be)(sqlite3_value*); + const void * (*value_text16le)(sqlite3_value*); + int (*value_type)(sqlite3_value*); + char *(*vmprintf)(const char*,va_list); + /* Added ??? */ + int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); + /* Added by 3.3.13 */ + int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + int (*clear_bindings)(sqlite3_stmt*); + /* Added by 3.4.1 */ + int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *)); + /* Added by 3.5.0 */ + int (*bind_zeroblob)(sqlite3_stmt*,int,int); + int (*blob_bytes)(sqlite3_blob*); + int (*blob_close)(sqlite3_blob*); + int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**); + int (*blob_read)(sqlite3_blob*,void*,int,int); + int (*blob_write)(sqlite3_blob*,const void*,int,int); + int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*)); + int (*file_control)(sqlite3*,const char*,int,void*); + sqlite3_int64 (*memory_highwater)(int); + sqlite3_int64 (*memory_used)(void); + sqlite3_mutex *(*mutex_alloc)(int); + void (*mutex_enter)(sqlite3_mutex*); + void (*mutex_free)(sqlite3_mutex*); + void (*mutex_leave)(sqlite3_mutex*); + int (*mutex_try)(sqlite3_mutex*); + int (*open_v2)(const char*,sqlite3**,int,const char*); + int (*release_memory)(int); + void (*result_error_nomem)(sqlite3_context*); + void (*result_error_toobig)(sqlite3_context*); + int (*sleep)(int); + void (*soft_heap_limit)(int); + sqlite3_vfs *(*vfs_find)(const char*); + int (*vfs_register)(sqlite3_vfs*,int); + int (*vfs_unregister)(sqlite3_vfs*); +}; + +/* +** The following macros redefine the API routines so that they are +** redirected throught the global sqlite3_api structure. +** +** This header file is also used by the loadext.c source file +** (part of the main SQLite library - not an extension) so that +** it can get access to the sqlite3_api_routines structure +** definition. But the main library does not want to redefine +** the API. So the redefinition macros are only valid if the +** SQLITE_CORE macros is undefined. +*/ +#ifndef SQLITE_CORE +#define sqlite3_aggregate_context sqlite3_api->aggregate_context +#define sqlite3_aggregate_count sqlite3_api->aggregate_count +#define sqlite3_bind_blob sqlite3_api->bind_blob +#define sqlite3_bind_double sqlite3_api->bind_double +#define sqlite3_bind_int sqlite3_api->bind_int +#define sqlite3_bind_int64 sqlite3_api->bind_int64 +#define sqlite3_bind_null sqlite3_api->bind_null +#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count +#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index +#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name +#define sqlite3_bind_text sqlite3_api->bind_text +#define sqlite3_bind_text16 sqlite3_api->bind_text16 +#define sqlite3_bind_value sqlite3_api->bind_value +#define sqlite3_busy_handler sqlite3_api->busy_handler +#define sqlite3_busy_timeout sqlite3_api->busy_timeout +#define sqlite3_changes sqlite3_api->changes +#define sqlite3_close sqlite3_api->close +#define sqlite3_collation_needed sqlite3_api->collation_needed +#define sqlite3_collation_needed16 sqlite3_api->collation_needed16 +#define sqlite3_column_blob sqlite3_api->column_blob +#define sqlite3_column_bytes sqlite3_api->column_bytes +#define sqlite3_column_bytes16 sqlite3_api->column_bytes16 +#define sqlite3_column_count sqlite3_api->column_count +#define sqlite3_column_database_name sqlite3_api->column_database_name +#define sqlite3_column_database_name16 sqlite3_api->column_database_name16 +#define sqlite3_column_decltype sqlite3_api->column_decltype +#define sqlite3_column_decltype16 sqlite3_api->column_decltype16 +#define sqlite3_column_double sqlite3_api->column_double +#define sqlite3_column_int sqlite3_api->column_int +#define sqlite3_column_int64 sqlite3_api->column_int64 +#define sqlite3_column_name sqlite3_api->column_name +#define sqlite3_column_name16 sqlite3_api->column_name16 +#define sqlite3_column_origin_name sqlite3_api->column_origin_name +#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 +#define sqlite3_column_table_name sqlite3_api->column_table_name +#define sqlite3_column_table_name16 sqlite3_api->column_table_name16 +#define sqlite3_column_text sqlite3_api->column_text +#define sqlite3_column_text16 sqlite3_api->column_text16 +#define sqlite3_column_type sqlite3_api->column_type +#define sqlite3_column_value sqlite3_api->column_value +#define sqlite3_commit_hook sqlite3_api->commit_hook +#define sqlite3_complete sqlite3_api->complete +#define sqlite3_complete16 sqlite3_api->complete16 +#define sqlite3_create_collation sqlite3_api->create_collation +#define sqlite3_create_collation16 sqlite3_api->create_collation16 +#define sqlite3_create_function sqlite3_api->create_function +#define sqlite3_create_function16 sqlite3_api->create_function16 +#define sqlite3_create_module sqlite3_api->create_module +#define sqlite3_create_module_v2 sqlite3_api->create_module_v2 +#define sqlite3_data_count sqlite3_api->data_count +#define sqlite3_db_handle sqlite3_api->db_handle +#define sqlite3_declare_vtab sqlite3_api->declare_vtab +#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache +#define sqlite3_errcode sqlite3_api->errcode +#define sqlite3_errmsg sqlite3_api->errmsg +#define sqlite3_errmsg16 sqlite3_api->errmsg16 +#define sqlite3_exec sqlite3_api->exec +#define sqlite3_expired sqlite3_api->expired +#define sqlite3_finalize sqlite3_api->finalize +#define sqlite3_free sqlite3_api->free +#define sqlite3_free_table sqlite3_api->free_table +#define sqlite3_get_autocommit sqlite3_api->get_autocommit +#define sqlite3_get_auxdata sqlite3_api->get_auxdata +#define sqlite3_get_table sqlite3_api->get_table +#define sqlite3_global_recover sqlite3_api->global_recover +#define sqlite3_interrupt sqlite3_api->interruptx +#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid +#define sqlite3_libversion sqlite3_api->libversion +#define sqlite3_libversion_number sqlite3_api->libversion_number +#define sqlite3_malloc sqlite3_api->malloc +#define sqlite3_mprintf sqlite3_api->mprintf +#define sqlite3_open sqlite3_api->open +#define sqlite3_open16 sqlite3_api->open16 +#define sqlite3_prepare sqlite3_api->prepare +#define sqlite3_prepare16 sqlite3_api->prepare16 +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#define sqlite3_profile sqlite3_api->profile +#define sqlite3_progress_handler sqlite3_api->progress_handler +#define sqlite3_realloc sqlite3_api->realloc +#define sqlite3_reset sqlite3_api->reset +#define sqlite3_result_blob sqlite3_api->result_blob +#define sqlite3_result_double sqlite3_api->result_double +#define sqlite3_result_error sqlite3_api->result_error +#define sqlite3_result_error16 sqlite3_api->result_error16 +#define sqlite3_result_int sqlite3_api->result_int +#define sqlite3_result_int64 sqlite3_api->result_int64 +#define sqlite3_result_null sqlite3_api->result_null +#define sqlite3_result_text sqlite3_api->result_text +#define sqlite3_result_text16 sqlite3_api->result_text16 +#define sqlite3_result_text16be sqlite3_api->result_text16be +#define sqlite3_result_text16le sqlite3_api->result_text16le +#define sqlite3_result_value sqlite3_api->result_value +#define sqlite3_rollback_hook sqlite3_api->rollback_hook +#define sqlite3_set_authorizer sqlite3_api->set_authorizer +#define sqlite3_set_auxdata sqlite3_api->set_auxdata +#define sqlite3_snprintf sqlite3_api->snprintf +#define sqlite3_step sqlite3_api->step +#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata +#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup +#define sqlite3_total_changes sqlite3_api->total_changes +#define sqlite3_trace sqlite3_api->trace +#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings +#define sqlite3_update_hook sqlite3_api->update_hook +#define sqlite3_user_data sqlite3_api->user_data +#define sqlite3_value_blob sqlite3_api->value_blob +#define sqlite3_value_bytes sqlite3_api->value_bytes +#define sqlite3_value_bytes16 sqlite3_api->value_bytes16 +#define sqlite3_value_double sqlite3_api->value_double +#define sqlite3_value_int sqlite3_api->value_int +#define sqlite3_value_int64 sqlite3_api->value_int64 +#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type +#define sqlite3_value_text sqlite3_api->value_text +#define sqlite3_value_text16 sqlite3_api->value_text16 +#define sqlite3_value_text16be sqlite3_api->value_text16be +#define sqlite3_value_text16le sqlite3_api->value_text16le +#define sqlite3_value_type sqlite3_api->value_type +#define sqlite3_vmprintf sqlite3_api->vmprintf +#define sqlite3_overload_function sqlite3_api->overload_function +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#define sqlite3_clear_bindings sqlite3_api->clear_bindings +#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob +#define sqlite3_blob_bytes sqlite3_api->blob_bytes +#define sqlite3_blob_close sqlite3_api->blob_close +#define sqlite3_blob_open sqlite3_api->blob_open +#define sqlite3_blob_read sqlite3_api->blob_read +#define sqlite3_blob_write sqlite3_api->blob_write +#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 +#define sqlite3_file_control sqlite3_api->file_control +#define sqlite3_memory_highwater sqlite3_api->memory_highwater +#define sqlite3_memory_used sqlite3_api->memory_used +#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc +#define sqlite3_mutex_enter sqlite3_api->mutex_enter +#define sqlite3_mutex_free sqlite3_api->mutex_free +#define sqlite3_mutex_leave sqlite3_api->mutex_leave +#define sqlite3_mutex_try sqlite3_api->mutex_try +#define sqlite3_open_v2 sqlite3_api->open_v2 +#define sqlite3_release_memory sqlite3_api->release_memory +#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem +#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig +#define sqlite3_sleep sqlite3_api->sleep +#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit +#define sqlite3_vfs_find sqlite3_api->vfs_find +#define sqlite3_vfs_register sqlite3_api->vfs_register +#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister +#endif /* SQLITE_CORE */ + +#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; +#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; + +#endif /* _SQLITE3EXT_H_ */ diff --git a/client/src/thirdparty/sqlite-3.4.2/src/sqliteInt.h b/client/src/thirdparty/sqlite-3.4.2/src/sqliteInt.h new file mode 100644 index 0000000..2f26f58 --- /dev/null +++ b/client/src/thirdparty/sqlite-3.4.2/src/sqliteInt.h @@ -0,0 +1,2089 @@ +/* +** 2001 September 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. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +** @(#) $Id: sqliteInt.h,v 1.659 2008/02/02 04:47:09 danielk1977 Exp $ +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. GCC is able to +** use these hints to generate better code, sometimes. +*/ +#if defined(__GNUC__) && 0 +# define likely(X) __builtin_expect((X),1) +# define unlikely(X) __builtin_expect((X),0) +#else +# define likely(X) !!(X) +# define unlikely(X) !!(X) +#endif + + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + + +#include "sqliteLimit.h" + +/* +** For testing purposes, the various size limit constants are really +** variables that we can modify in the testfixture. +*/ +#ifdef SQLITE_TEST + #undef SQLITE_MAX_LENGTH + #undef SQLITE_MAX_COLUMN + #undef SQLITE_MAX_SQL_LENGTH + #undef SQLITE_MAX_EXPR_DEPTH + #undef SQLITE_MAX_COMPOUND_SELECT + #undef SQLITE_MAX_VDBE_OP + #undef SQLITE_MAX_FUNCTION_ARG + #undef SQLITE_MAX_VARIABLE_NUMBER + #undef SQLITE_MAX_PAGE_SIZE + #undef SQLITE_MAX_PAGE_COUNT + #undef SQLITE_MAX_LIKE_PATTERN_LENGTH + + #define SQLITE_MAX_LENGTH sqlite3MAX_LENGTH + #define SQLITE_MAX_COLUMN sqlite3MAX_COLUMN + #define SQLITE_MAX_SQL_LENGTH sqlite3MAX_SQL_LENGTH + #define SQLITE_MAX_EXPR_DEPTH sqlite3MAX_EXPR_DEPTH + #define SQLITE_MAX_COMPOUND_SELECT sqlite3MAX_COMPOUND_SELECT + #define SQLITE_MAX_VDBE_OP sqlite3MAX_VDBE_OP + #define SQLITE_MAX_FUNCTION_ARG sqlite3MAX_FUNCTION_ARG + #define SQLITE_MAX_VARIABLE_NUMBER sqlite3MAX_VARIABLE_NUMBER + #define SQLITE_MAX_PAGE_SIZE sqlite3MAX_PAGE_SIZE + #define SQLITE_MAX_PAGE_COUNT sqlite3MAX_PAGE_COUNT + #define SQLITE_MAX_LIKE_PATTERN_LENGTH sqlite3MAX_LIKE_PATTERN_LENGTH + + extern int sqlite3MAX_LENGTH; + extern int sqlite3MAX_COLUMN; + extern int sqlite3MAX_SQL_LENGTH; + extern int sqlite3MAX_EXPR_DEPTH; + extern int sqlite3MAX_COMPOUND_SELECT; + extern int sqlite3MAX_VDBE_OP; + extern int sqlite3MAX_FUNCTION_ARG; + extern int sqlite3MAX_VARIABLE_NUMBER; + extern int sqlite3MAX_PAGE_SIZE; + extern int sqlite3MAX_PAGE_COUNT; + extern int sqlite3MAX_LIKE_PATTERN_LENGTH; +#endif + + +/* +** The SQLITE_THREADSAFE macro must be defined as either 0 or 1. +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy +*/ +#if !defined(SQLITE_THREADSAFE) +#if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +#else +# define SQLITE_THREADSAFE 1 +#endif +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most unix systems. But Mac OS X is different. +** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, +** so it is omitted there. See ticket #2673. +** +** Later we learn that _XOPEN_SOURCE is poorly or incorrectly +** implemented on some systems. So we avoid defining it at all +** if it is already defined or if it is unneeded because we are +** not doing a threadsafe build. Ticket #2681. +** +** See also ticket #2741. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE +# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ +#endif + +#if defined(SQLITE_TCL) || defined(TCLSH) +# include +#endif + +/* +** Many people are failing to set -DNDEBUG=1 when compiling SQLite. +** Setting NDEBUG makes the code smaller and run faster. So the following +** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 +** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + +#include "sqlite3.h" +#include "hash.h" +#include "parse.h" +#include +#include +#include +#include +#include + +#define sqlite3_isnan(X) ((X)!=(X)) + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (0x7fffffffffffffff) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** If the following macro is set to 1, then NULL values are considered +** distinct when determining whether or not two entries are the same +** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, +** OCELOT, and Firebird all work. The SQL92 spec explicitly says this +** is the way things are suppose to work. +** +** If the following macro is set to 0, the NULLs are indistinct for +** a UNIQUE index. In this mode, you can only have a single NULL entry +** for a column declared UNIQUE. This is the way Informix and SQL Server +** work. +*/ +#define NULL_DISTINCT_FOR_UNIQUE 1 + +/* +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. +*/ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 1 +#endif + +/* +** Provide a default value for TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef TEMP_STORE +# define TEMP_STORE 1 +#endif + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# define UINT32_TYPE unsigned int +#endif +#ifndef UINT16_TYPE +# define UINT16_TYPE unsigned short int +#endif +#ifndef INT16_TYPE +# define INT16_TYPE short int +#endif +#ifndef UINT8_TYPE +# define UINT8_TYPE unsigned char +#endif +#ifndef INT8_TYPE +# define INT8_TYPE signed char +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ +typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ +typedef INT16_TYPE i16; /* 2-byte signed integer */ +typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ +typedef UINT8_TYPE i8; /* 1-byte signed integer */ + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +#ifdef SQLITE_AMALGAMATION +const int sqlite3One; +#else +extern const int sqlite3one; +#endif +#if defined(i386) || defined(__i386__) || defined(_M_IX86) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) (sizeof(X)/sizeof(X[0])) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct CollSeq CollSeq; +typedef struct Column Column; +typedef struct Db Db; +typedef struct Schema Schema; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct FKey FKey; +typedef struct FuncDef FuncDef; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct Select Select; +typedef struct SrcList SrcList; +typedef struct StrAccum StrAccum; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct TriggerStack TriggerStack; +typedef struct TriggerStep TriggerStep; +typedef struct Trigger Trigger; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque +** pointer types (i.e. FuncDef) defined above. +*/ +#include "btree.h" +#include "vdbe.h" +#include "pager.h" + +#include "os.h" +#include "mutex.h" + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +struct Db { + char *zName; /* Name of this database */ + Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at synching data to disk */ + void *pAux; /* Auxiliary data. Usually NULL */ + void (*xFreeAux)(void*); /* Routine to free pAux */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +** +** If there are no virtual tables configured in this schema, the +** Schema.db variable is set to NULL. After the first virtual table +** has been added, it is set to point to the database connection +** used to create the connection. Once a virtual table has been +** added to the Schema structure and the Schema.db variable populated, +** only that database connection may use the Schema to prepare +** statements. +*/ +struct Schema { + int schema_cookie; /* Database schema version number for this file */ + Hash tblHash; /* All tables indexed by name */ + Hash idxHash; /* All (named) indices indexed by name */ + Hash trigHash; /* All triggers indexed by name */ + Hash aFKey; /* Foreign keys indexed by to-table */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3 *db; /* "Owner" connection. See comment above */ +#endif +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.flags field. +*/ +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) + +/* +** Allowed values for the DB.flags field. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ +#define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ + + +/* +** Each database is an instance of the following structure. +** +** The sqlite.lastRowid records the last insert rowid generated by an +** insert statement. Inserts on views do not affect its value. Each +** trigger has its own context, so that lastRowid can be updated inside +** triggers as usual. The previous value will be restored once the trigger +** exits. Upon entering a before or instead of trigger, lastRowid is no +** longer (since after version 2.8.12) reset to -1. +** +** The sqlite.nChange does not count changes within triggers and keeps no +** context. It is reset at start of sqlite3_exec. +** The sqlite.lsChange represents the number of changes made by the last +** insert, update, or delete statement. It remains constant throughout the +** length of a statement and is then updated by OP_SetCounts. It keeps a +** context stack just like lastRowid so that the count of changes +** within a trigger is not seen outside the trigger. Changes to views do not +** affect the value of lsChange. +** The sqlite.csChange keeps track of the number of current changes (since +** the last statement) and is used to update sqlite_lsChange. +** +** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16 +** store the most recent error code and, if applicable, string. The +** internal function sqlite3Error() is used to set these variables +** consistently. +*/ +struct sqlite3 { + sqlite3_vfs *pVfs; /* OS Interface */ + int nDb; /* Number of backends currently in use */ + Db *aDb; /* All backends */ + int flags; /* Miscellanous flags. See below */ + int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + u8 mallocFailed; /* True if we have seen a malloc failure */ + signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + int nTable; /* Number of tables in the database */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 priorNewRowid; /* Last randomly generated ROWID */ + int magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + sqlite3_mutex *mutex; /* Connection mutex */ + struct sqlite3InitInfo { /* Information used during initialization */ + int iDb; /* When back is being initialized */ + int newTnum; /* Rootpage of table being initialized */ + u8 busy; /* TRUE if currently initializing */ + } init; + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared libraray handles */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + int activeVdbeCnt; /* Number of vdbes currently executing */ + void (*xTrace)(void*,const char*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ + void (*xProfile)(void*,const char*,u64); /* Profiling function */ + void *pProfileArg; /* Argument to profile function */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); + void *pCollNeededArg; + sqlite3_value *pErr; /* Most recent error message */ + char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ + char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + int nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + Hash aModule; /* populated by sqlite3_create_module() */ + Table *pVTab; /* vtab with active Connect/Create method */ + sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ +#endif + Hash aFunc; /* All functions that can be in SQL exprs */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + int busyTimeout; /* Busy handler timeout, in msec */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ +#ifdef SQLITE_SSE + sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ +#endif + u8 dfltLockMode; /* Default locking-mode for attached dbs */ +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + +/* +** Possible values for the sqlite.flags and or Db.flags fields. +** +** On sqlite.flags, the SQLITE_InTrans value means that we have +** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement +** transaction is active on that particular database file. +*/ +#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ +#define SQLITE_InTrans 0x00000008 /* True if in a transaction */ +#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ +#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when + ** accessing read-only databases */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ +#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ + +#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */ +#define SQLITE_SharedCache 0x00080000 /* Cache sharing is enabled */ +#define SQLITE_Vtab 0x00100000 /* There exists a virtual table */ + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ + u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */ + u8 flags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ + char zName[1]; /* SQL name of the function. MUST BE LAST */ +}; + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** Possible values for FuncDef.flags +*/ +#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */ + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zType; /* Data type for this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* True if there is a NOT NULL constraint */ + u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ + char affinity; /* One of the SQLITE_AFF_... values */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isHidden; /* True if this column is 'hidden' */ +#endif +}; + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** There may two seperate implementations of the collation function, one +** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that +** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine +** native byte order. When a collation sequence is invoked, SQLite selects +** the version that will require the least expensive encoding +** translations, if any. +** +** The CollSeq.pUser member variable is an extra parameter that passed in +** as the first argument to the UTF-8 comparison function, xCmp. +** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, +** xCmp16. +** +** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + u8 type; /* One of the SQLITE_COLL_... values below */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** Allowed values of CollSeq flags: +*/ +#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */ +#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */ +#define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */ +#define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */ + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by number the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'a'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P4 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. +*/ +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' + +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x67 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +*/ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_NULLEQUAL 0x10 /* compare NULLs equal */ +#define SQLITE_STOREP2 0x80 /* Store result in reg[P2] rather than jump */ + +/* +** 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. Table.hasPrimKey is true 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 Table.isEphem +** is true, 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. +*/ +struct Table { + char *zName; /* Name of the table */ + int nCol; /* Number of columns in this table */ + Column *aCol; /* Information about each column */ + int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ + Index *pIndex; /* List of SQL indexes on this table. */ + int tnum; /* Root BTree node for this table (see note above) */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + int nRef; /* Number of pointers to this Table */ + Trigger *pTrigger; /* List of SQL triggers on this table */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ + char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + Expr *pCheck; /* The AND of all CHECK constraints */ +#endif +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ +#endif + u8 readOnly; /* True if this table should not be written by the user */ + u8 isEphem; /* True if created using OP_OpenEphermeral */ + u8 hasPrimKey; /* True if there exists a primary key */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ + u8 autoInc; /* True if the integer primary key is autoincrement */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isVirtual; /* True if this is a virtual table */ + u8 isCommit; /* True once the CREATE TABLE has been committed */ + Module *pMod; /* Pointer to the implementation of the module */ + sqlite3_vtab *pVtab; /* Pointer to the module instance */ + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ +#endif + Schema *pSchema; /* Schema that contains this table */ +}; + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) ((X)->isVirtual) +# define IsHiddenColumn(X) ((X)->isHidden) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existance of the to-table is not checked +** until an attempt is made to insert data into the from-table. +** +** The sqlite.aFKey hash table stores pointers to this structure +** given the name of a to-table. For each to-table, all foreign keys +** associated with that table are on a linked list using the FKey.pNextTo +** field. +*/ +struct FKey { + Table *pFrom; /* The table that constains the REFERENCES clause */ + FKey *pNextFrom; /* Next foreign key in pFrom */ + char *zTo; /* Name of table that the key points to */ + FKey *pNextTo; /* Next foreign key that points to zTo */ + int nCol; /* Number of columns in this key */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } *aCol; /* One entry for each of nCol column s */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ + u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ + u8 insertConf; /* How to resolve conflicts that occur on INSERT */ +}; + +/* +** SQLite supports many different ways to resolve a constraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 99 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +** +** If the KeyInfo.incrKey value is true and the comparison would +** otherwise be equal, then return a result as if the second key +** were larger. +*/ +struct KeyInfo { + sqlite3 *db; /* The database connection */ + u8 enc; /* Text encoding - one of the TEXT_Utf* values */ + u8 incrKey; /* Increase 2nd key by epsilon before comparison */ + u8 prefixIsEqual; /* Treat a prefix as equal */ + int nField; /* Number of entries in aColl[] */ + u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +*/ +struct Index { + char *zName; /* Name of this index */ + int nColumn; /* Number of columns in the table used by this index */ + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ + unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + int tnum; /* Page containing root of this index in database file */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assuptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const unsigned char *z; /* Text of the token. Not NULL-terminated! */ + unsigned dyn : 1; /* True for malloced memory, false for static */ + unsigned n : 31; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + ExprList *pGroupBy; /* The group by clause */ + int nSortingColumn; /* Number of columns in the sorting index */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nColumnAlloc; /* Number of slots allocated for aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephermeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ + int nFuncAlloc; /* Number of slots allocated for aFunc[] */ +}; + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list +** of argument if the expression is a function. +** +** Expr.token is the operator token for this node. For some expressions +** that have subexpressions, Expr.token can be the complete text that gave +** rise to the Expr. In the latter case, the token is marked as being +** a compound token. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is a function, the Expr.iTable is an integer code +** representing which function. If the expression is an unbound variable +** marker (a question mark character '?' in the original SQL) then the +** Expr.iTable holds the index number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** The Expr.pSelect field points to a SELECT statement. The SELECT might +** be the right operand of an IN operator. Or, if a scalar SELECT appears +** in an expression the opcode is TK_SELECT and Expr.pSelect is the only +** operand. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + u16 flags; /* Various flags. See below */ + CollSeq *pColl; /* The collation type of the column or 0 */ + Expr *pLeft, *pRight; /* Left and right subnodes */ + ExprList *pList; /* A list of expressions used as function arguments + ** or in " IN (aCol[] or ->aFunc[] */ + int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + Select *pSelect; /* When the expression is a sub-select. Also the + ** right side of " IN (

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 z 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